home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 1995 #5 & #6 / Amiga Plus CD - 1995 - No. 5 and 6.iso / pd / netz / term / extras / source / term-source.lha / termAux.c < prev    next >
C/C++ Source or Header  |  1995-06-17  |  87KB  |  4,682 lines

  1. /*
  2. **    termAux.c
  3. **
  4. **    Miscellaneous support routines
  5. **
  6. **    Copyright © 1990-1995 by Olaf `Olsen' Barthel
  7. **        All Rights Reserved
  8. */
  9.  
  10. #include "termGlobal.h"
  11.  
  12.     /* This variable stores the current state of the
  13.      * dialing menu items.
  14.      */
  15.  
  16. STATIC BYTE DialItemsAvailable = TRUE;
  17.  
  18.     /* Current timer state. */
  19.  
  20. STATIC BYTE TimerRunning = FALSE;
  21.  
  22. STATIC VOID
  23. StuffChar(VOID)
  24. {
  25.     __emit(0x16C0);    /* MOVE D0,(A3)+ */
  26. }
  27.  
  28.     /* SPrintf(STRPTR Buffer,STRPTR FormatString,...):
  29.      *
  30.      *    Just like sprintf(), but using the ROM routines.
  31.      */
  32.  
  33. VOID __stdargs
  34. SPrintf(STRPTR Buffer,STRPTR FormatString,...)
  35. {
  36.     va_list VarArgs;
  37.  
  38.     va_start(VarArgs,FormatString);
  39.     RawDoFmt(FormatString,VarArgs,(VOID (*)())StuffChar,Buffer);
  40.     va_end(VarArgs);
  41. }
  42.  
  43.     /* VSPrintf(STRPTR Buffer,STRPTR FormatString,va_list VarArgs):
  44.      *
  45.      *    Just like vsprintf(), but using the ROM routines.
  46.      */
  47.  
  48. VOID __regargs
  49. VSPrintf(STRPTR Buffer,STRPTR FormatString,va_list VarArgs)
  50. {
  51.     RawDoFmt(FormatString,VarArgs,(VOID (*)())StuffChar,Buffer);
  52. }
  53.  
  54.     /* Atol(STRPTR Buffer):
  55.      *
  56.      *    Convert ASCII representation to long word.
  57.      */
  58.  
  59. LONG __regargs
  60. Atol(STRPTR Buffer)
  61. {
  62.     LONG Result;
  63.  
  64.     StrToLong(Buffer,&Result);
  65.  
  66.     return(Result);
  67. }
  68.  
  69.     /* StripSpaces(STRPTR String):
  70.      *
  71.      *    Strip leading and trailing spaces from a string.
  72.      */
  73.  
  74. VOID __regargs
  75. StripSpaces(STRPTR String)
  76. {
  77.     if(String)
  78.     {
  79.         STRPTR    To = String;
  80.         WORD    Len;
  81.  
  82.         while(*String == ' ')
  83.             String++;
  84.  
  85.         if(Len = strlen(String))
  86.         {
  87.             while(Len > 0 && String[Len - 1] == ' ')
  88.                 Len--;
  89.  
  90.             while(Len--)
  91.                 *To++ = *String++;
  92.         }
  93.  
  94.         *To = 0;
  95.     }
  96. }
  97.  
  98.     /* ReplaceWindowInfo(struct WindowInfo *NewInfo):
  99.      *
  100.      *    Drop the window info into the right place.
  101.      */
  102.  
  103. VOID __regargs
  104. ReplaceWindowInfo(struct WindowInfo *NewInfo)
  105. {
  106.     WORD i;
  107.  
  108.     for(i = 0 ; i < WINDOW_COUNT ; i++)
  109.     {
  110.         if(WindowInfoTable[i] . ID == NewInfo -> ID)
  111.         {
  112.             CopyMem(NewInfo,&WindowInfoTable[i],sizeof(struct WindowInfo));
  113.  
  114.             break;
  115.         }
  116.     }
  117. }
  118.  
  119.     /* PutWindowInfo():
  120.      *
  121.      *    Store window size and position relative to
  122.      *    the main window.
  123.      */
  124.  
  125. VOID __regargs
  126. PutWindowInfo(UBYTE ID,LONG Left,LONG Top,LONG Width,LONG Height)
  127. {
  128.     struct WindowInfo    *Info;
  129.     WORD             i;
  130.     LONG             WindowLeft,
  131.                  WindowTop,
  132.                  WindowWidth,
  133.                  WindowHeight;
  134.     ULONG             IntuiLock;
  135.  
  136.     for(i = 0 ; i < WINDOW_COUNT ; i++)
  137.     {
  138.         if(WindowInfoTable[i] . ID == ID)
  139.         {
  140.             Info = &WindowInfoTable[i];
  141.  
  142.             break;
  143.         }
  144.     }
  145.  
  146.     IntuiLock = LockIBase(NULL);
  147.  
  148.     WindowLeft    = Window -> LeftEdge;
  149.     WindowTop    = Window -> TopEdge;
  150.     WindowWidth    = Window -> Width;
  151.     WindowHeight    = Window -> Height;
  152.  
  153.     UnlockIBase(IntuiLock);
  154.  
  155.     Forbid();
  156.  
  157.     Info -> WindowFlags = NULL;
  158.  
  159.     if(WindowWidth == Width && WindowLeft == Left)
  160.         Info -> WindowFlags |= WC_EXPANDWIDTH;
  161.     else
  162.     {
  163.         if(Left == WindowLeft + WindowWidth)
  164.             Info -> WindowFlags |= WC_ALIGNSIDE;
  165.  
  166.         if(WindowLeft == Left)
  167.             Info -> WindowFlags |= WC_ALIGNLEFT;
  168.  
  169.         if(WindowLeft + WindowWidth == Left + Width)
  170.             Info -> WindowFlags |= WC_ALIGNRIGHT;
  171.     }
  172.  
  173.     if(WindowHeight == Height && WindowTop == Top)
  174.         Info -> WindowFlags |= WC_EXPANDHEIGHT;
  175.     else
  176.     {
  177.         if(Top == WindowTop + WindowHeight)
  178.             Info -> WindowFlags |= WC_ALIGNBELOW;
  179.  
  180.         if(WindowTop == Top)
  181.             Info -> WindowFlags |= WC_ALIGNTOP;
  182.  
  183.         if(WindowTop + WindowHeight == Top + Height)
  184.             Info -> WindowFlags |= WC_ALIGNBOTTOM;
  185.     }
  186.  
  187.     Info -> Left    = Left;
  188.     Info -> Top    = Top;
  189.     Info -> Width    = Width;
  190.     Info -> Height    = Height;
  191.  
  192.     Permit();
  193. }
  194.  
  195.     /* GetWindowInfo():
  196.      *
  197.      *    Set the window size and position in relation to
  198.      *    the main window.
  199.      */
  200.  
  201. VOID __regargs
  202. GetWindowInfo(UBYTE ID,LONG *Left,LONG *Top,LONG *Width,LONG *Height,LONG DefWidth,LONG DefHeight)
  203. {
  204.     struct WindowInfo    *Info;
  205.     WORD             i;
  206.     LONG             WindowLeft,
  207.                  WindowTop,
  208.                  WindowWidth,
  209.                  WindowHeight;
  210.     ULONG             IntuiLock;
  211.  
  212.     if(Window)
  213.     {
  214.         if(DefWidth && DefWidth < Window -> Width / 2)
  215.             DefWidth = Window -> Width / 2;
  216.  
  217.         if(DefHeight && DefHeight < Window -> Height / 2)
  218.             DefHeight = Window -> Height / 2;
  219.     }
  220.  
  221.     for(i = 0 ; i < WINDOW_COUNT ; i++)
  222.     {
  223.         if(WindowInfoTable[i] . ID == ID)
  224.         {
  225.             Info = &WindowInfoTable[i];
  226.  
  227.             break;
  228.         }
  229.     }
  230.  
  231.     if(Info && ID == WINDOW_MAIN)
  232.     {
  233.         *Left    = Info -> Left;
  234.         *Top    = Info -> Top;
  235.  
  236.         return;
  237.     }
  238.  
  239.     if(Window)
  240.     {
  241.         IntuiLock = LockIBase(NULL);
  242.  
  243.         WindowLeft    = Window -> LeftEdge;
  244.         WindowTop    = Window -> TopEdge + Window -> BorderTop;
  245.         WindowWidth    = Window -> Width;
  246.         WindowHeight    = Window -> Height - Window -> BorderTop;
  247.  
  248.         UnlockIBase(IntuiLock);
  249.     }
  250.  
  251.     Forbid();
  252.  
  253.     if(*Width)
  254.     {
  255.         if(Info -> Width)
  256.             *Left = Info -> Left;
  257.         else
  258.             *Left = WindowLeft + (WindowWidth - *Width) / 2;
  259.     }
  260.     else
  261.     {
  262.         if(DefWidth && !Info -> Width)
  263.         {
  264.             *Width    = DefWidth;
  265.             *Left    = WindowLeft + (WindowWidth - *Width) / 2;
  266.         }
  267.         else
  268.         {
  269.             if(Info -> Width)
  270.             {
  271.                 *Width    = Info -> Width;
  272.                 *Left    = Info -> Left;
  273.             }
  274.             else
  275.             {
  276. /*                *Width    = WindowWidth / 2;*/
  277. /*                *Left    = WindowLeft + WindowWidth / 4;*/
  278.  
  279.                 *Width    = WindowWidth;
  280.                 *Left    = WindowLeft;
  281.             }
  282.         }
  283.     }
  284.  
  285.     if(*Height)
  286.     {
  287.         if(Info -> Height)
  288.             *Top = Info -> Top;
  289.         else
  290.             *Top = WindowTop + (WindowHeight - *Height) / 2;
  291.     }
  292.     else
  293.     {
  294.         if(DefHeight && !Info -> Height)
  295.         {
  296.             *Height    = DefHeight;
  297.             *Top    = WindowTop + (WindowHeight - *Height) / 2;
  298.         }
  299.         else
  300.         {
  301.             if(Info -> Height)
  302.             {
  303.                 *Height    = Info -> Height;
  304.                 *Top    = Info -> Top;
  305.             }
  306.             else
  307.             {
  308. /*                *Height    = WindowHeight / 2;*/
  309. /*                *Top    = WindowTop + WindowHeight / 4;*/
  310.  
  311.                 *Height    = WindowHeight;
  312.                 *Top    = WindowTop;
  313.             }
  314.         }
  315.     }
  316.  
  317.     if(Info -> WindowFlags & WC_ALIGNSIDE)
  318.         *Left = WindowLeft + WindowWidth;
  319.  
  320.     if(Info -> WindowFlags & WC_ALIGNBELOW)
  321.         *Top = WindowTop + WindowHeight;
  322.  
  323.     if(Info -> WindowFlags & WC_ALIGNLEFT)
  324.         *Left = WindowLeft;
  325.  
  326.     if(Info -> WindowFlags & WC_ALIGNTOP)
  327.         *Top = WindowTop;
  328.  
  329.     if(Info -> WindowFlags & WC_ALIGNRIGHT)
  330.         *Left = WindowLeft + WindowWidth - *Width;
  331.  
  332.     if(Info -> WindowFlags & WC_ALIGNBOTTOM)
  333.         *Top = WindowTop + WindowHeight - *Height;
  334.  
  335.     if(Info -> WindowFlags & WC_EXPANDWIDTH)
  336.         *Width = WindowWidth;
  337.  
  338.     if(Info -> WindowFlags & WC_EXPANDHEIGHT)
  339.         *Height = WindowHeight;
  340.  
  341.     Permit();
  342. }
  343.  
  344.     /* GetBitMapDepth(struct BitMap *BitMap):
  345.      *
  346.      *    Return the depth of a BitMap.
  347.      */
  348.  
  349. LONG __regargs
  350. GetBitMapDepth(struct BitMap *BitMap)
  351. {
  352.     LONG Depth;
  353.  
  354.     if(Kick30)
  355.         Depth = (LONG)GetBitMapAttr(BitMap,BMA_DEPTH);
  356.     else
  357.         Depth = BitMap -> Depth;
  358.  
  359.     if(Depth > 8)
  360.         Depth = 8;
  361.  
  362.     return(Depth);
  363. }
  364.  
  365.     /* GetDPI(ULONG Mode,ULONG *X_DPI,ULONG *Y_DPI):
  366.      *
  367.      *    Get screen DPI resolution values.
  368.      */
  369.  
  370. VOID __regargs
  371. GetDPI(ULONG Mode,ULONG *X_DPI,ULONG *Y_DPI)
  372. {
  373.     struct DisplayInfo DisplayInfo;
  374.  
  375.     if(GetDisplayInfoData(NULL,(APTR)&DisplayInfo,sizeof(struct DisplayInfo),DTAG_DISP,Mode))
  376.     {
  377.         *X_DPI = (35 * 140) / DisplayInfo . PixelSpeed;
  378.         *Y_DPI = (*X_DPI * DisplayInfo . Resolution . x) / DisplayInfo . Resolution . y;
  379.     }
  380.     else
  381.         *X_DPI = *Y_DPI = 72;
  382. }
  383.  
  384.     /* AddProtection(STRPTR FileName,ULONG Mask):
  385.      *
  386.      *    Set bits in the protection mask of a file.
  387.      */
  388.  
  389. VOID __regargs
  390. AddProtection(STRPTR Name,ULONG Mask)
  391. {
  392.     struct FileInfoBlock *FileInfo;
  393.  
  394.     if(FileInfo = (struct FileInfoBlock *)AllocDosObject(DOS_FIB,TAG_DONE))
  395.     {
  396.         BPTR FileLock;
  397.  
  398.         if(FileLock = Lock(Name,ACCESS_READ))
  399.         {
  400.             if(Examine(FileLock,FileInfo))
  401.             {
  402.                 UnLock(FileLock);
  403.  
  404.                 SetProtection(Name,FileInfo -> fib_Protection | Mask);
  405.             }
  406.             else
  407.                 UnLock(FileLock);
  408.         }
  409.  
  410.         FreeDosObject(DOS_FIB,FileInfo);
  411.     }
  412. }
  413.  
  414.     /* GetPubScreenName(struct Screen *Screen,STRPTR Name):
  415.      *
  416.      *    Get the name of a public screen.
  417.      */
  418.  
  419. BYTE __regargs
  420. GetPubScreenName(struct Screen *Screen,STRPTR Name)
  421. {
  422.     struct List        *PubScreenList;
  423.     struct PubScreenNode    *ScreenNode;
  424.  
  425.     PubScreenList = LockPubScreenList();
  426.  
  427.     for(ScreenNode = (struct PubScreenNode *)PubScreenList -> lh_Head ; ScreenNode -> psn_Node . ln_Succ ; ScreenNode = (struct PubScreenNode *)ScreenNode -> psn_Node . ln_Succ)
  428.     {
  429.         if(ScreenNode -> psn_Screen == Screen)
  430.         {
  431.             strcpy(Name,ScreenNode -> psn_Node . ln_Name);
  432.  
  433.             UnlockPubScreenList();
  434.  
  435.             return(TRUE);
  436.         }
  437.     }
  438.  
  439.     UnlockPubScreenList();
  440.  
  441.     return(FALSE);
  442. }
  443.  
  444.     /* InitSinglePort(struct MsgPort *Port):
  445.      *
  446.      *    Initialize a plain MsgPort (as created on the stack) for
  447.      *    usage. Don't try this at home, kids!
  448.      */
  449.  
  450. VOID __regargs
  451. InitSinglePort(struct MsgPort *Port)
  452. {
  453.     memset(Port,0,sizeof(struct MsgPort));
  454.  
  455.     Port -> mp_Flags    = PA_SIGNAL;
  456.     Port -> mp_SigBit    = SIGB_SINGLE;
  457.     Port -> mp_SigTask    = SysBase -> ThisTask;
  458.  
  459.     NewList(&Port -> mp_MsgList);
  460. }
  461.  
  462.     /* GoodStream(BPTR Stream):
  463.      *
  464.      *    Check to see whether the current input file
  465.      *    is an interactive stream.
  466.      */
  467.  
  468. BYTE __regargs
  469. GoodStream(BPTR Stream)
  470. {
  471.     if(!Stream)
  472.     {
  473.         struct Process *ThisProcess = (struct Process *)SysBase -> ThisTask;
  474.  
  475.         Stream = ThisProcess -> pr_CIS;
  476.     }
  477.  
  478.     if(Stream)
  479.     {
  480.         struct FileHandle *Handle = (struct FileHandle *)BADDR(Stream);
  481.  
  482.         if(Handle -> fh_Type)
  483.         {
  484.             if(IsInteractive(Stream))
  485.                 return(TRUE);
  486.         }
  487.     }
  488.  
  489.     return(FALSE);
  490. }
  491.  
  492.     /* GetProgramIcon():
  493.      *
  494.      *    Try to find the icon of the program.
  495.      */
  496.  
  497. struct DiskObject *
  498. GetProgramIcon()
  499. {
  500.     struct DiskObject *Icon = NULL;
  501.  
  502.         /* Run from Workbench? */
  503.  
  504.     if(WBenchMsg)
  505.     {
  506.             /* Sanity check. */
  507.  
  508.         if(WBenchMsg -> sm_ArgList)
  509.         {
  510.                 /* Yet another sanity check. */
  511.  
  512.             if(WBenchMsg -> sm_ArgList -> wa_Name)
  513.             {
  514.                     /* Try to find the icon in the current directory. */
  515.  
  516.                 if(Icon = GetDiskObjectNew(WBenchMsg -> sm_ArgList -> wa_Name))
  517.                 {
  518.                     if(Icon -> do_Type != WBTOOL)
  519.                     {
  520.                         FreeDiskObject(Icon);
  521.  
  522.                         Icon = NULL;
  523.                     }
  524.                 }
  525.  
  526.                 if(!Icon)
  527.                 {
  528.                     BPTR NewLock;
  529.  
  530.                         /* Move to the directory the
  531.                          * program was run from.
  532.                          */
  533.  
  534.                     if(NewLock = Lock("PROGDIR:",ACCESS_READ))
  535.                     {
  536.                         BPTR OldLock;
  537.  
  538.                         OldLock = CurrentDir(NewLock);
  539.  
  540.                             /* Try to fetch the icon, use the
  541.                              * default name if necessary.
  542.                              */
  543.  
  544.                         if(Icon = GetDiskObjectNew(WBenchMsg -> sm_ArgList -> wa_Name))
  545.                         {
  546.                             if(Icon -> do_Type != WBTOOL)
  547.                             {
  548.                                 FreeDiskObject(Icon);
  549.  
  550.                                 Icon = NULL;
  551.                             }
  552.                         }
  553.  
  554.                         if(!Icon)
  555.                         {
  556.                             if(Icon = GetDiskObjectNew("term"))
  557.                             {
  558.                                 if(Icon -> do_Type != WBTOOL)
  559.                                 {
  560.                                     FreeDiskObject(Icon);
  561.  
  562.                                     Icon = NULL;
  563.                                 }
  564.                             }
  565.                         }
  566.  
  567.                         CurrentDir(OldLock);
  568.  
  569.                         UnLock(NewLock);
  570.                     }
  571.                 }
  572.             }
  573.         }
  574.     }
  575.  
  576.         /* Still no success. */
  577.  
  578.     if(!Icon)
  579.     {
  580.             /* Use the default names. */
  581.  
  582.         if(Icon = GetDiskObjectNew("term"))
  583.         {
  584.             if(Icon -> do_Type != WBTOOL)
  585.             {
  586.                 FreeDiskObject(Icon);
  587.  
  588.                 Icon = NULL;
  589.             }
  590.         }
  591.  
  592.         if(!Icon)
  593.         {
  594.             if(Icon = GetDiskObjectNew("PROGDIR:term"))
  595.             {
  596.                 if(Icon -> do_Type != WBTOOL)
  597.                 {
  598.                     FreeDiskObject(Icon);
  599.  
  600.                     Icon = NULL;
  601.                 }
  602.             }
  603.         }
  604.     }
  605.  
  606.     return(Icon);
  607. }
  608.  
  609.     /* GetPenIndex(LONG Pen):
  610.      *
  611.      *    Get the table index corresponding to an on-screen
  612.      *    text rendering pen.
  613.      */
  614.  
  615. LONG __regargs
  616. GetPenIndex(LONG Pen)
  617. {
  618.     LONG i;
  619.  
  620.     for(i = 0 ; i < 16 ; i++)
  621.     {
  622.         if(MappedPens[0][i] == Pen)
  623.             return(i);
  624.     }
  625. }
  626.  
  627.     /* GetScreenWidth(struct Window *Window):
  628.      *
  629.      *    Query the current screen width.
  630.      */
  631.  
  632. LONG __regargs
  633. GetScreenWidth(struct Window *Window)
  634. {
  635.     if(Window)
  636.     {
  637.         if(Window -> Width > ScreenWidth || Window -> LeftEdge < -Window -> WScreen -> LeftEdge || Window -> LeftEdge + Window -> WScreen -> LeftEdge + Window -> Width > ScreenWidth)
  638.             return(ScreenWidth);
  639.         else
  640.             return(Window -> Width - (Window -> BorderLeft + Window -> BorderRight));
  641.     }
  642.     else
  643.         return(ScreenWidth);
  644. }
  645.  
  646.     /* GetScreenHeight(struct Window *Window):
  647.      *
  648.      *    Query the current screen height.
  649.      */
  650.  
  651. LONG __regargs
  652. GetScreenHeight(struct Window *Window)
  653. {
  654.     if(Window)
  655.     {
  656.         if(Window -> Height > ScreenHeight || Window -> TopEdge < -Window -> WScreen -> TopEdge || Window -> TopEdge + Window -> WScreen -> TopEdge + Window -> Height > ScreenHeight)
  657.             return(ScreenHeight);
  658.         else
  659.             return(Window -> Height - (Window -> BorderTop + Window -> BorderBottom));
  660.     }
  661.     else
  662.         return(ScreenHeight);
  663. }
  664.  
  665.     /* GetLeft(struct Screen *Screen):
  666.      *
  667.      *    Get the screen left edge.
  668.      */
  669.  
  670. STATIC LONG __regargs
  671. GetLeft(struct Screen *Screen)
  672. {
  673.     if(Screen -> LeftEdge >= 0)
  674.         return(0);
  675.     else
  676.         return(-Screen -> LeftEdge);
  677. }
  678.  
  679.     /* GetScreenLeft(struct Window *Window):
  680.      *
  681.      *    Query the current screen left edge.
  682.      */
  683.  
  684. LONG __regargs
  685. GetScreenLeft(struct Window *Window)
  686. {
  687.     if(Window)
  688.     {
  689.         if(Window -> Width > ScreenWidth || Window -> LeftEdge < -Window -> WScreen -> LeftEdge || Window -> LeftEdge + Window -> WScreen -> LeftEdge + Window -> Width > ScreenWidth)
  690.             return(GetLeft(Window -> WScreen));
  691.         else
  692.             return(Window -> LeftEdge + Window -> BorderLeft);
  693.     }
  694.     else
  695.         return(GetLeft(DefaultPubScreen ? DefaultPubScreen : SharedScreen));
  696. }
  697.  
  698.     /* GetTop(struct Screen *Screen):
  699.      *
  700.      *    Get the screen top edge.
  701.      */
  702.  
  703. STATIC LONG __regargs
  704. GetTop(struct Screen *Screen)
  705. {
  706.     if(Screen -> TopEdge >= 0)
  707.         return(0);
  708.     else
  709.         return(-Screen -> TopEdge);
  710. }
  711.  
  712.     /* GetScreenTop(struct Window *Window):
  713.      *
  714.      *    Query the current screen top edge.
  715.      */
  716.  
  717. LONG __regargs
  718. GetScreenTop(struct Window *Window)
  719. {
  720.     if(Window)
  721.     {
  722.         if(Window -> Height > ScreenHeight || Window -> TopEdge < -Window -> WScreen -> TopEdge || Window -> TopEdge + Window -> WScreen -> TopEdge + Window -> Height > ScreenHeight)
  723.             return(GetTop(Window -> WScreen));
  724.         else
  725.             return(Window -> TopEdge + Window -> BorderTop);
  726.     }
  727.     else
  728.         return(GetTop(DefaultPubScreen ? DefaultPubScreen : SharedScreen));
  729. }
  730.  
  731.     /* OldGetAPen(struct RastPort *RPort):
  732.      *
  733.      *    Query the current primary rendering colour (old style).
  734.      */
  735.  
  736. ULONG
  737. OldGetAPen(struct RastPort *RPort)
  738. {
  739.     return((ULONG)RPort -> FgPen);
  740. }
  741.  
  742.     /* OldGetBPen(struct RastPort *RPort):
  743.      *
  744.      *    Query the current seconary rendering colour (old style).
  745.      */
  746.  
  747. ULONG
  748. OldGetBPen(struct RastPort *RPort)
  749. {
  750.     return((ULONG)RPort -> BgPen);
  751. }
  752.  
  753.     /* OldGetDrMd(struct RastPort *RPort):
  754.      *
  755.      *    Query the current drawing mode (old style).
  756.      */
  757.  
  758. ULONG
  759. OldGetDrMd(struct RastPort *RPort)
  760. {
  761.     return((ULONG)RPort -> DrawMode);
  762. }
  763.  
  764.     /* OldSetWrMsk(struct RastPort *RPort,ULONG Mask):
  765.      *
  766.      *    Set the rendering plane mask (old style).
  767.      */
  768.  
  769. ULONG
  770. OldSetWrMsk(struct RastPort *RPort,ULONG Mask)
  771. {
  772.     if(UseMasking)
  773.         RPort -> Mask = Mask;
  774.  
  775.     return((ULONG)1);
  776. }
  777.  
  778.     /* NewGetAPen(struct RastPort *RPort):
  779.      *
  780.      *    Query the current primary rendering colour (new style).
  781.      */
  782.  
  783. ULONG
  784. NewGetAPen(struct RastPort *RPort)
  785. {
  786.     return(GetAPen(RPort));
  787. }
  788.  
  789.     /* NewGetBPen(struct RastPort *RPort):
  790.      *
  791.      *    Query the current seconary rendering colour (new style).
  792.      */
  793.  
  794. ULONG
  795. NewGetBPen(struct RastPort *RPort)
  796. {
  797.     return(GetBPen(RPort));
  798. }
  799.  
  800.     /* NewGetDrMd(struct RastPort *RPort):
  801.      *
  802.      *    Query the current drawing mode (new style).
  803.      */
  804.  
  805. ULONG
  806. NewGetDrMd(struct RastPort *RPort)
  807. {
  808.     return(GetDrMd(RPort));
  809. }
  810.  
  811.     /* NewSetWrMsk(struct RastPort *RPort,ULONG Mask):
  812.      *
  813.      *    Set the rendering plane mask (new style).
  814.      */
  815.  
  816. ULONG
  817. NewSetWrMsk(struct RastPort *RPort,ULONG Mask)
  818. {
  819.     if(UseMasking)
  820.         return(SetWriteMask(RPort,Mask));
  821.     else
  822.         return((ULONG)1);
  823. }
  824.  
  825.     /* SetWait(struct Window *Window):
  826.      *
  827.      *    Set the busy wait mouse pointer.
  828.      */
  829.  
  830. VOID __regargs
  831. SetWait(struct Window *Window)
  832. {
  833.     if(Kick30)
  834.     {
  835.         SetWindowPointer(Window,
  836.             WA_BusyPointer,        TRUE,
  837.             WA_PointerDelay,    TRUE,
  838.         TAG_DONE);
  839.     }
  840.     else
  841.         SetPointer(Window,Stopwatch,16,16,-6,0);
  842. }
  843.  
  844.     /* ClrWait(struct Window *Window):
  845.      *
  846.      *    Remove the busy wait mouse pointer.
  847.      */
  848.  
  849. VOID __regargs
  850. ClrWait(struct Window *Window)
  851. {
  852.     if(Kick30)
  853.         SetWindowPointer(Window,TAG_DONE);
  854.     else
  855.         ClearPointer(Window);
  856. }
  857.  
  858.     /* GetModeName(ULONG Mode):
  859.      *
  860.      *    Get the name of a display mode.
  861.      */
  862.  
  863. STRPTR __regargs
  864. GetModeName(ULONG Mode)
  865. {
  866.     STATIC UBYTE __far    Buffer[DISPLAYNAMELEN + 1];
  867.     struct NameInfo        NameInfo;
  868.  
  869.     if(GetDisplayInfoData(NULL,(APTR)&NameInfo,sizeof(struct NameInfo),DTAG_NAME,Mode))
  870.         strcpy(Buffer,NameInfo . Name);
  871.     else
  872.     {
  873.         struct DimensionInfo DimensionInfo;
  874.  
  875.         if(GetDisplayInfoData(NULL,(APTR)&DimensionInfo,sizeof(struct DimensionInfo),DTAG_DIMS,Mode))
  876.         {
  877.             STRPTR MonitorName;
  878.  
  879.             switch(Mode & MONITOR_ID_MASK)
  880.             {
  881.                 case NTSC_MONITOR_ID:
  882.  
  883.                     MonitorName = "NTSC: ";
  884.                     break;
  885.  
  886.                 case PAL_MONITOR_ID:
  887.  
  888.                     MonitorName = "PAL: ";
  889.                     break;
  890.  
  891.                 case VGA_MONITOR_ID:
  892.  
  893.                     MonitorName = "VGA: ";
  894.                     break;
  895.  
  896.                 case A2024_MONITOR_ID:
  897.  
  898.                     MonitorName = "A2024: ";
  899.                     break;
  900.  
  901.                 default:
  902.  
  903.                     MonitorName = "";
  904.                     break;
  905.             }
  906.  
  907.             SPrintf(Buffer,"%s%ld × %ld",MonitorName,DimensionInfo . TxtOScan . MaxX - DimensionInfo . TxtOScan . MinX + 1,DimensionInfo . TxtOScan . MaxY - DimensionInfo . TxtOScan . MinY + 1);
  908.         }
  909.         else
  910.             strcpy(Buffer,LocaleString(MSG_SCREENPANEL_UNKNOWN_TXT));
  911.     }
  912.  
  913.     return(Buffer);
  914. }
  915.  
  916.     /* ModeOkay(ULONG ID):
  917.      *
  918.      *    Checks whether a display mode ID will do for deep
  919.      *    screen bitmaps.
  920.      */
  921.  
  922. BYTE __regargs
  923. ModeOkay(ULONG ID)
  924. {
  925.     struct DimensionInfo DimensionInfo;
  926.  
  927.     if(GetDisplayInfoData(NULL,(APTR)&DimensionInfo,sizeof(struct DimensionInfo),DTAG_DIMS,ID))
  928.     {
  929.         if(DimensionInfo . MaxDepth >= 4)
  930.             return(TRUE);
  931.     }
  932.  
  933.     return(FALSE);
  934. }
  935.  
  936.     /* SetClipMenu(BYTE Mode):
  937.      *
  938.      *    Enable/disable the copy/clear selection menu items.
  939.      */
  940.  
  941. VOID __regargs
  942. SetClipMenu(BYTE Mode)
  943. {
  944.     if(Mode && RasterEnabled)
  945.     {
  946.         OnItem(MEN_COPY);
  947.         OnItem(MEN_CLEAR);
  948.     }
  949.     else
  950.     {
  951.         OffItem(MEN_COPY);
  952.         OffItem(MEN_CLEAR);
  953.     }
  954. }
  955.  
  956.     /* SetRedialMenu():
  957.      *
  958.      *    Make the `redial' menu item available or make it
  959.      *    unavailable.
  960.      */
  961.  
  962. VOID
  963. SetRedialMenu()
  964. {
  965.     BYTE Mode;
  966.  
  967.     if(DialList)
  968.     {
  969.         if(DialList -> lh_Head -> ln_Succ)
  970.             Mode = TRUE;
  971.         else
  972.             Mode = FALSE;
  973.     }
  974.     else
  975.         Mode = FALSE;
  976.  
  977.     if(Mode && (DialItemsAvailable || Config -> MiscConfig -> ProtectiveMode))
  978.         OnItem(MEN_REDIAL);
  979.     else
  980.         OffItem(MEN_REDIAL);
  981. }
  982.  
  983.     /* SetDialMenu(BYTE Mode):
  984.      *
  985.      *    Block or enable the dialing menu.
  986.      */
  987.  
  988. VOID __regargs
  989. SetDialMenu(BYTE Mode)
  990. {
  991.     if(Window && Menu)
  992.     {
  993.         if(Mode || Config -> MiscConfig -> ProtectiveMode)
  994.         {
  995.             if(DialList)
  996.             {
  997.                 if(DialList -> lh_Head -> ln_Succ)
  998.                     OnItem(MEN_REDIAL);
  999.                 else
  1000.                     OffItem(MEN_REDIAL);
  1001.             }
  1002.             else
  1003.                 OffItem(MEN_REDIAL);
  1004.  
  1005.             OnItem(MEN_DIAL_NUMBER);
  1006.  
  1007.             if(FirstDialMenu != -1)
  1008.                 OnItem(MEN_EXTRA_DIAL);
  1009.         }
  1010.         else
  1011.         {
  1012.             OffItem(MEN_REDIAL);
  1013.             OffItem(MEN_DIAL_NUMBER);
  1014.  
  1015.             if(FirstDialMenu != -1)
  1016.                 OffItem(MEN_EXTRA_DIAL);
  1017.         }
  1018.  
  1019.         DialItemsAvailable = Mode;
  1020.     }
  1021. }
  1022.  
  1023.     /* SetTransferMenu(BYTE Mode):
  1024.      *
  1025.      *    Block or enable the transfer menu.
  1026.      */
  1027.  
  1028. VOID __regargs
  1029. SetTransferMenu(BYTE Mode)
  1030. {
  1031.     if(Window && Menu)
  1032.     {
  1033.         BOOLEAN    ValidDefault,
  1034.             ValidASCIIDownload,
  1035.             ValidASCIIUpload,
  1036.             ValidTextDownload,
  1037.             ValidTextUpload,
  1038.             ValidBinaryDownload,
  1039.             ValidBinaryUpload;
  1040.  
  1041.         if(!Config -> TransferConfig -> DefaultLibrary[0] || !Mode)
  1042.             ValidDefault = FALSE;
  1043.         else
  1044.             ValidDefault = TRUE;
  1045.  
  1046.         switch(Config -> TransferConfig -> ASCIIUploadType)
  1047.         {
  1048.             case XFER_INTERNAL:
  1049.  
  1050.                 ValidASCIIUpload = TRUE;
  1051.                 break;
  1052.  
  1053.             case XFER_DEFAULT:
  1054.  
  1055.                 ValidASCIIUpload = ValidDefault;
  1056.                 break;
  1057.  
  1058.             case XFER_XPR:
  1059.             case XFER_EXTERNALPROGRAM:
  1060.  
  1061.                 ValidASCIIUpload = Config -> TransferConfig -> ASCIIUploadLibrary[0];
  1062.                 break;
  1063.         }
  1064.  
  1065.         switch(Config -> TransferConfig -> ASCIIDownloadType)
  1066.         {
  1067.             case XFER_INTERNAL:
  1068.  
  1069.                 ValidASCIIDownload = TRUE;
  1070.                 break;
  1071.  
  1072.             case XFER_DEFAULT:
  1073.  
  1074.                 ValidASCIIDownload = ValidDefault;
  1075.                 break;
  1076.  
  1077.             case XFER_XPR:
  1078.             case XFER_EXTERNALPROGRAM:
  1079.  
  1080.                 ValidASCIIDownload = Config -> TransferConfig -> ASCIIDownloadLibrary[0];
  1081.                 break;
  1082.         }
  1083.  
  1084.  
  1085.         switch(Config -> TransferConfig -> TextUploadType)
  1086.         {
  1087.             case XFER_DEFAULT:
  1088.  
  1089.                 ValidTextUpload = ValidDefault;
  1090.                 break;
  1091.  
  1092.             case XFER_XPR:
  1093.             case XFER_EXTERNALPROGRAM:
  1094.  
  1095.                 ValidTextUpload = Config -> TransferConfig -> TextUploadLibrary[0];
  1096.                 break;
  1097.         }
  1098.  
  1099.         switch(Config -> TransferConfig -> TextDownloadType)
  1100.         {
  1101.             case XFER_DEFAULT:
  1102.  
  1103.                 ValidTextDownload = ValidDefault;
  1104.                 break;
  1105.  
  1106.             case XFER_XPR:
  1107.             case XFER_EXTERNALPROGRAM:
  1108.  
  1109.                 ValidTextDownload = Config -> TransferConfig -> TextDownloadLibrary[0];
  1110.                 break;
  1111.         }
  1112.  
  1113.         switch(Config -> TransferConfig -> BinaryUploadType)
  1114.         {
  1115.             case XFER_DEFAULT:
  1116.  
  1117.                 ValidBinaryUpload = ValidDefault;
  1118.                 break;
  1119.  
  1120.             case XFER_XPR:
  1121.             case XFER_EXTERNALPROGRAM:
  1122.  
  1123.                 ValidBinaryUpload = Config -> TransferConfig -> BinaryUploadLibrary[0];
  1124.                 break;
  1125.         }
  1126.  
  1127.         switch(Config -> TransferConfig -> BinaryDownloadType)
  1128.         {
  1129.             case XFER_DEFAULT:
  1130.  
  1131.                 ValidBinaryDownload = ValidDefault;
  1132.                 break;
  1133.  
  1134.             case XFER_XPR:
  1135.             case XFER_EXTERNALPROGRAM:
  1136.  
  1137.                 ValidBinaryDownload = Config -> TransferConfig -> BinaryDownloadLibrary[0];
  1138.                 break;
  1139.         }
  1140.  
  1141.         if(ValidASCIIUpload)
  1142.             OnItem(MEN_UPLOAD_ASCII);
  1143.         else
  1144.             OffItem(MEN_UPLOAD_ASCII);
  1145.  
  1146.         if(ValidASCIIDownload)
  1147.             OnItem(MEN_DOWNLOAD_ASCII);
  1148.         else
  1149.             OffItem(MEN_DOWNLOAD_ASCII);
  1150.  
  1151.         if(ValidTextUpload)
  1152.         {
  1153.             OnItem(MEN_UPLOAD_TEXT);
  1154.             OnItem(MEN_EDIT_AND_UPLOAD_TEXT);
  1155.         }
  1156.         else
  1157.         {
  1158.             OffItem(MEN_UPLOAD_TEXT);
  1159.             OffItem(MEN_EDIT_AND_UPLOAD_TEXT);
  1160.         }
  1161.  
  1162.         if(ValidTextDownload)
  1163.             OnItem(MEN_DOWNLOAD_TEXT);
  1164.         else
  1165.             OffItem(MEN_DOWNLOAD_TEXT);
  1166.  
  1167.         if(ValidBinaryUpload)
  1168.             OnItem(MEN_UPLOAD_BINARY);
  1169.         else
  1170.             OffItem(MEN_UPLOAD_BINARY);
  1171.  
  1172.         if(ValidBinaryDownload)
  1173.             OnItem(MEN_DOWNLOAD_BINARY);
  1174.         else
  1175.             OffItem(MEN_DOWNLOAD_BINARY);
  1176.  
  1177.         if(ValidDefault)
  1178.             OnItem(MEN_TRANSFER);
  1179.         else
  1180.             OffItem(MEN_TRANSFER);
  1181.     }
  1182. }
  1183.  
  1184.     /* SetRasterMenu(BYTE Mode):
  1185.      *
  1186.      *    Block or enable the menu entries associated with
  1187.      *    functions to access the screen raster.
  1188.      */
  1189.  
  1190. VOID __regargs
  1191. SetRasterMenu(BYTE Mode)
  1192. {
  1193.     if(Window && Menu)
  1194.     {
  1195.         if(Mode)
  1196.         {
  1197.             OnItem(MEN_SAVE_AS_TEXT);
  1198.             OnItem(MEN_PRINT_SCREEN);
  1199.         }
  1200.         else
  1201.         {
  1202.             OffItem(MEN_SAVE_AS_TEXT);
  1203.             OffItem(MEN_PRINT_SCREEN);
  1204.         }
  1205.     }
  1206. }
  1207.  
  1208.     /* PickFont(struct Window *Window,STRPTR Name,WORD *Points,BYTE MonoSpaced):
  1209.      *
  1210.      *    Pick a font using asl.library
  1211.      */
  1212.  
  1213. BYTE __regargs
  1214. PickFont(struct Window *Window,STRPTR Name,WORD *Points,BYTE MonoSpaced)
  1215. {
  1216.     struct FontRequester    *Requester;
  1217.     struct TagItem         DimensionTags[5];
  1218.     BYTE             Result = FALSE;
  1219.  
  1220.     if(Requester = (struct FontRequester *)AllocAslRequestTags(ASL_FontRequest,
  1221.         ASL_Window,                    Window,
  1222.         ASLFO_InitialFrontPen,                DrawInfo -> dri_Pens[TEXTPEN],
  1223.         ASLFO_InitialBackPen,                DrawInfo -> dri_Pens[BACKGROUNDPEN],
  1224.         MonoSpaced ? ASL_FuncFlags : TAG_IGNORE,    FONF_FIXEDWIDTH,
  1225.     TAG_MORE,GetDimensionTags(NULL,DimensionTags)))
  1226.     {
  1227.         if(AslRequestTags(Requester,
  1228.             ASL_FontName,    Name,
  1229.             ASL_FontHeight,    *Points,
  1230.         TAG_DONE))
  1231.         {
  1232.             PutDimensionTags(NULL,Requester -> fo_LeftEdge,Requester -> fo_TopEdge,Requester -> fo_Width,Requester -> fo_Height);
  1233.  
  1234.             strcpy(Name,Requester -> fo_Attr . ta_Name);
  1235.  
  1236.             *Points = Requester -> fo_Attr . ta_YSize;
  1237.  
  1238.             Result = TRUE;
  1239.         }
  1240.  
  1241.         FreeAslRequest(Requester);
  1242.     }
  1243.  
  1244.     return(Result);
  1245. }
  1246.  
  1247.     /* ExtractString():
  1248.      *
  1249.      *    Extracts a string from a list separated by `|' characters.
  1250.      */
  1251.  
  1252. STRPTR __regargs
  1253. ExtractString(STRPTR String,STRPTR Destination,BYTE ReturnEnd)
  1254. {
  1255.     STRPTR OldString;
  1256.  
  1257.     if(ReturnEnd)
  1258.         OldString = NULL;
  1259.     else
  1260.         OldString = String;
  1261.  
  1262.     while(*String)
  1263.     {
  1264.         if(*String == '|')
  1265.         {
  1266.             *Destination = 0;
  1267.  
  1268.             String++;
  1269.  
  1270.             if(*String)
  1271.                 return(String);
  1272.             else
  1273.                 return(OldString);
  1274.         }
  1275.         else
  1276.             *Destination++ = *String++;
  1277.     }
  1278.  
  1279.     *Destination = 0;
  1280.  
  1281.     return(OldString);
  1282. }
  1283.  
  1284.     /* GetListSize(struct List *List):
  1285.      *
  1286.      *    Determine the number of entries in a list.
  1287.      */
  1288.  
  1289. LONG __regargs
  1290. GetListSize(struct List *List)
  1291. {
  1292.     struct Node    *Node    = List -> lh_Head;
  1293.     LONG         i    = 0;
  1294.  
  1295.     while(Node -> ln_Succ)
  1296.     {
  1297.         i++;
  1298.  
  1299.         Node = Node -> ln_Succ;
  1300.     }
  1301.  
  1302.     return(i);
  1303. }
  1304.  
  1305.     /* GetListNode(LONG Offset,struct List *List):
  1306.      *
  1307.      *    Return the n-th Node entry in a standard exec list.
  1308.      */
  1309.  
  1310. struct Node * __regargs
  1311. GetListNode(LONG Offset,struct List *List)
  1312. {
  1313.     struct Node    *Node;
  1314.     LONG         i;
  1315.  
  1316.     Node = List -> lh_Head;
  1317.  
  1318.     for(i = 0 ; i < Offset ; i++)
  1319.     {
  1320.         if(!Node -> ln_Succ -> ln_Succ)
  1321.             return(NULL);
  1322.  
  1323.         Node = Node -> ln_Succ;
  1324.     }
  1325.  
  1326.     return(Node);
  1327. }
  1328.  
  1329.     /* CreateNode(STRPTR Name):
  1330.      *
  1331.      *    Put a name string into a list node.
  1332.      */
  1333.  
  1334. struct Node * __regargs
  1335. CreateNode(STRPTR Name)
  1336. {
  1337.     struct Node *Node;
  1338.  
  1339.     if(Node = (struct Node *)AllocVecPooled(sizeof(struct Node) + strlen(Name) + 1,MEMF_ANY | MEMF_PUBLIC))
  1340.     {
  1341.         Node -> ln_Name = (STRPTR)(Node + 1);
  1342.  
  1343.         strcpy(Node -> ln_Name,Name);
  1344.     }
  1345.  
  1346.     return(Node);
  1347. }
  1348.  
  1349.     /* FreeNode(struct Node *Node):
  1350.      *
  1351.      *    Remove and deallocate a node.
  1352.      */
  1353.  
  1354. VOID __regargs
  1355. FreeNode(struct Node *Node)
  1356. {
  1357.     Remove(Node);
  1358.  
  1359.     FreeVecPooled(Node);
  1360. }
  1361.  
  1362.     /* FreeList(struct List *List):
  1363.      *
  1364.      *    Remove all nodes from the list
  1365.      *    and free them on the way.
  1366.      */
  1367.  
  1368. VOID __regargs
  1369. FreeList(struct List *List)
  1370. {
  1371.     struct Node *Node,*NextNode;
  1372.  
  1373.     Node = List -> lh_Head;
  1374.  
  1375.     while(NextNode = Node -> ln_Succ)
  1376.     {
  1377.         FreeNode(Node);
  1378.  
  1379.         Node = NextNode;
  1380.     }
  1381. }
  1382.  
  1383.     /* GetNodeOffset(struct Node *Node,struct List *List):
  1384.      *
  1385.      *    Scan a list for a certain node and return
  1386.      *    its position.
  1387.      */
  1388.  
  1389. LONG __regargs
  1390. GetNodeOffset(struct Node *Node,struct List *List)
  1391. {
  1392.     struct Node    *ListNode;
  1393.     LONG         Offset = 0;
  1394.  
  1395.     ListNode = List -> lh_Head;
  1396.  
  1397.     while(ListNode -> ln_Succ)
  1398.     {
  1399.         if(Node == ListNode)
  1400.             return(Offset);
  1401.         else
  1402.         {
  1403.             Offset++;
  1404.  
  1405.             ListNode = ListNode -> ln_Succ;
  1406.         }
  1407.     }
  1408.  
  1409.     return(~0);
  1410. }
  1411.  
  1412.     /* MoveList(struct List *From,struct List *To):
  1413.      *
  1414.      *    Move the contents of a list to a different list.
  1415.      */
  1416.  
  1417. VOID __regargs
  1418. MoveList(struct List *From,struct List *To)
  1419. {
  1420.     struct Node *Node,*NextNode;
  1421.  
  1422.     Node = From -> lh_Head;
  1423.  
  1424.     while(NextNode = Node -> ln_Succ)
  1425.     {
  1426.         Remove(Node);
  1427.  
  1428.         AddTail(To,Node);
  1429.  
  1430.         Node = NextNode;
  1431.     }
  1432. }
  1433.  
  1434.     /* LogAction(STRPTR String,...):
  1435.      *
  1436.      *    Write an action to the default log file.
  1437.      */
  1438.  
  1439. VOID __stdargs
  1440. LogAction(STRPTR String,...)
  1441. {
  1442.     if(Config -> CaptureConfig -> LogActions && Config -> CaptureConfig -> LogFileName[0])
  1443.     {
  1444.         UBYTE    DummyBuffer[512];
  1445.         BPTR    File;
  1446.  
  1447.         va_list    VarArgs;
  1448.  
  1449.             /* Build a valid string. */
  1450.  
  1451.         va_start(VarArgs,String);
  1452.         VSPrintf(DummyBuffer,String,VarArgs);
  1453.         va_end(VarArgs);
  1454.  
  1455.             /* Does the log file already exist? */
  1456.  
  1457.         if(GetFileSize(Config -> CaptureConfig -> LogFileName))
  1458.         {
  1459.                 /* It does, let's append the data. */
  1460.  
  1461.             if(File = Open(Config -> CaptureConfig -> LogFileName,MODE_READWRITE))
  1462.             {
  1463.                 if(Seek(File,0,OFFSET_END) == -1)
  1464.                 {
  1465.                     Close(File);
  1466.  
  1467.                     File = NULL;
  1468.                 }
  1469.             }
  1470.         }
  1471.         else
  1472.         {
  1473.                 /* Create a new file. */
  1474.  
  1475.             if(File = Open(Config -> CaptureConfig -> LogFileName,MODE_NEWFILE))
  1476.                 FPrintf(File,LocaleString(MSG_TERMAUX_DATE_TIME_ACTION_TXT));
  1477.         }
  1478.  
  1479.             /* The file is open, build the date/time string and
  1480.              * write the log action.
  1481.              */
  1482.  
  1483.         if(File)
  1484.         {
  1485.             UBYTE        DateBuffer[40],
  1486.                     TimeBuffer[40];
  1487.             struct DateTime    DateTime;
  1488.  
  1489.             DateStamp(&DateTime . dat_Stamp);
  1490.  
  1491.             DateTime . dat_Format    = FORMAT_DOS;
  1492.             DateTime . dat_Flags    = NULL;
  1493.             DateTime . dat_StrDay    = NULL;
  1494.             DateTime . dat_StrDate    = DateBuffer;
  1495.             DateTime . dat_StrTime    = TimeBuffer;
  1496.  
  1497.             if(DateToStr(&DateTime))
  1498.             {
  1499.                 StripSpaces(TimeBuffer);
  1500.  
  1501.                 FPrintf(File,"%-9s %8s %s\n",DateBuffer,TimeBuffer,DummyBuffer);
  1502.             }
  1503.  
  1504.                 /* Done! */
  1505.  
  1506.             Close(File);
  1507.         }
  1508.     }
  1509. }
  1510.  
  1511.     /* FlushMsg(struct Window *Window):
  1512.      *
  1513.      *    Cancel all pending messages of a window.
  1514.      */
  1515.  
  1516. VOID __regargs
  1517. FlushMsg(struct Window *Window)
  1518. {
  1519.     struct IntuiMessage *Massage;
  1520.  
  1521.     while(Massage = (struct IntuiMessage *)GetMsg(Window -> UserPort))
  1522.         ReplyMsg(&Massage -> ExecMessage);
  1523. }
  1524.  
  1525.     /* GetString(STRPTR Prompt,STRPTR Buffer):
  1526.      *
  1527.      *    Get a string from the user, very much the same as xpr_gets,
  1528.      *    but also including the `Load File' gadget.
  1529.      */
  1530.  
  1531. BYTE __regargs
  1532. GetString(BYTE LoadGadget,BYTE Password,WORD MaxChars,STRPTR Prompt,STRPTR Buffer)
  1533. {
  1534.     enum    {    GAD_OK=1,GAD_CANCEL,GAD_STRING };
  1535.  
  1536.     struct LayoutHandle    *Handle;
  1537.     BYTE             Success = FALSE;
  1538.     UBYTE             LocalBuffer[256];
  1539.  
  1540.     if(!MaxChars)
  1541.         MaxChars = 255;
  1542.  
  1543.     if(MaxChars > 255)
  1544.     {
  1545.         CopyMem(Buffer,LocalBuffer,255);
  1546.  
  1547.         LocalBuffer[255] = 0;
  1548.  
  1549.         MaxChars = 255;
  1550.     }
  1551.     else
  1552.         strcpy(LocalBuffer,Buffer);
  1553.  
  1554.     if(!Prompt)
  1555.         Prompt = LocaleString(MSG_TERMXPR_INPUT_REQUIRED_TXT);
  1556.  
  1557.     if(Handle = LT_CreateHandleTags(Window -> WScreen,
  1558.         LH_LocaleHook,    &LocaleHook,
  1559.     TAG_DONE))
  1560.     {
  1561.         struct Window *PanelWindow;
  1562.  
  1563.         LT_New(Handle,
  1564.             LA_Type,    VERTICAL_KIND,
  1565.         TAG_DONE);
  1566.         {
  1567.             LT_New(Handle,
  1568.                 LA_Type,    VERTICAL_KIND,
  1569.                 LA_LabelText,    Prompt,
  1570.             TAG_DONE);
  1571.             {
  1572.                 if(Password)
  1573.                 {
  1574.                     LT_New(Handle,
  1575.                         LA_Type,    PASSWORD_KIND,
  1576.                         LA_STRPTR,    LocalBuffer,
  1577.                         LA_ID,        GAD_STRING,
  1578.                         LA_Chars,    40,
  1579.                         GTST_MaxChars,    MaxChars,
  1580.                     TAG_DONE);
  1581.                 }
  1582.                 else
  1583.                 {
  1584.                     LT_New(Handle,
  1585.                         LA_Type,    STRING_KIND,
  1586.                         LA_STRPTR,    LocalBuffer,
  1587.                         LA_ID,        GAD_STRING,
  1588.                         LA_Chars,    60,
  1589.                         LAST_Picker,    LoadGadget,
  1590.                     TAG_DONE);
  1591.                 }
  1592.  
  1593.                 LT_EndGroup(Handle);
  1594.             }
  1595.  
  1596.             LT_New(Handle,
  1597.                 LA_Type,VERTICAL_KIND,
  1598.             TAG_DONE);
  1599.             {
  1600.                 LT_New(Handle,
  1601.                     LA_Type,    XBAR_KIND,
  1602.                     LAXB_FullSize,    TRUE,
  1603.                 TAG_DONE);
  1604.  
  1605.                 LT_EndGroup(Handle);
  1606.             }
  1607.  
  1608.             LT_New(Handle,LA_Type,HORIZONTAL_KIND,
  1609.                 LAGR_SameSize,    TRUE,
  1610.                 LAGR_Spread,    TRUE,
  1611.             TAG_DONE);
  1612.             {
  1613.                 LT_New(Handle,
  1614.                     LA_Type,    BUTTON_KIND,
  1615.                     LA_LabelID,    MSG_TERMXPR_OKAY_GAD,
  1616.                     LA_ID,        GAD_OK,
  1617.                     LABT_ReturnKey,    TRUE,
  1618.                     LABT_ExtraFat,    TRUE,
  1619.                 TAG_DONE);
  1620.  
  1621.                 LT_New(Handle,
  1622.                     LA_Type,    BUTTON_KIND,
  1623.                     LA_LabelID,    MSG_GLOBAL_CANCEL_GAD,
  1624.                     LA_ID,        GAD_CANCEL,
  1625.                     LABT_EscKey,    TRUE,
  1626.                     LABT_ExtraFat,    TRUE,
  1627.                 TAG_DONE);
  1628.  
  1629.                 LT_EndGroup(Handle);
  1630.             }
  1631.         }
  1632.  
  1633.         if(PanelWindow = LT_Layout(Handle,LocaleString(MSG_GLOBAL_ENTER_TEXT_TXT),NULL,0,0,IDCMP_CLOSEWINDOW,0,
  1634.             LAWN_HelpHook,        &GuideHook,
  1635.             LAWN_Parent,        Window,
  1636.             WA_DepthGadget,        TRUE,
  1637.             WA_CloseGadget,        TRUE,
  1638.             WA_DragBar,        TRUE,
  1639.             WA_RMBTrap,        TRUE,
  1640.             WA_Activate,        TRUE,
  1641.         TAG_DONE))
  1642.         {
  1643.             struct IntuiMessage    *Message;
  1644.             BOOLEAN             Done = FALSE;
  1645.             ULONG             MsgClass,
  1646.                          MsgQualifier;
  1647.             UWORD             MsgCode;
  1648.             struct Gadget        *MsgGadget;
  1649.  
  1650.             LT_Activate(Handle,GAD_STRING);
  1651.  
  1652.             PushWindow(PanelWindow);
  1653.  
  1654.             LT_ShowWindow(Handle,TRUE);
  1655.  
  1656.             do
  1657.             {
  1658.                 if(Wait(PORTMASK(PanelWindow -> UserPort) | SIG_BREAK) & SIG_BREAK)
  1659.                     break;
  1660.  
  1661.                 while(Message = (struct IntuiMessage *)GT_GetIMsg(PanelWindow -> UserPort))
  1662.                 {
  1663.                     MsgClass    = Message -> Class;
  1664.                     MsgQualifier    = Message -> Qualifier;
  1665.                     MsgCode        = Message -> Code;
  1666.                     MsgGadget    = (struct Gadget *)Message -> IAddress;
  1667.  
  1668.                     GT_ReplyIMsg(Message);
  1669.  
  1670.                     LT_HandleInput(Handle,MsgQualifier,&MsgClass,&MsgCode,&MsgGadget);
  1671.  
  1672.                     if(MsgClass == IDCMP_CLOSEWINDOW)
  1673.                         Done = TRUE;
  1674.  
  1675.                     if(MsgClass == IDCMP_GADGETUP)
  1676.                     {
  1677.                         switch(MsgGadget -> GadgetID)
  1678.                         {
  1679.                             case GAD_STRING:
  1680.  
  1681.                                 if(MsgCode == '\r')
  1682.                                 {
  1683.                                     strcpy(Buffer,LocalBuffer);
  1684.  
  1685.                                     Success = Done = TRUE;
  1686.  
  1687.                                     LT_PressButton(Handle,GAD_OK);
  1688.                                 }
  1689.  
  1690.                                 break;
  1691.  
  1692.                             case GAD_OK:
  1693.  
  1694.                                 LT_UpdateStrings(Handle);
  1695.  
  1696.                                 strcpy(Buffer,LocalBuffer);
  1697.  
  1698.                                 Success = Done = TRUE;
  1699.                                 break;
  1700.  
  1701.                             case GAD_CANCEL:
  1702.  
  1703.                                 Done = TRUE;
  1704.                                 break;
  1705.                         }
  1706.                     }
  1707.  
  1708.                     if(MsgClass == IDCMP_IDCMPUPDATE && MsgGadget -> GadgetID == GAD_STRING)
  1709.                     {
  1710.                         UBYTE             DummyBuffer[MAX_FILENAME_LENGTH],
  1711.                                     *DummyChar;
  1712.                         struct FileRequester    *FileRequest;
  1713.  
  1714.                         LT_LockWindow(PanelWindow);
  1715.  
  1716.                         SplitFileName(LocalBuffer,&DummyChar,DummyBuffer);
  1717.  
  1718.                         if(FileRequest = GetFile(PanelWindow,LocaleString(MSG_TERMAUX_LOAD_FILE_TXT),DummyBuffer,DummyChar,DummyBuffer,NULL,FALSE,FALSE,FALSE,LocaleString(MSG_GLOBAL_SELECT_TXT),TRUE))
  1719.                         {
  1720.                             LT_SetAttributes(Handle,GAD_STRING,GTST_String,DummyBuffer,TAG_DONE);
  1721.  
  1722.                             FreeAslRequest(FileRequest);
  1723.                         }
  1724.  
  1725.                         LT_UnlockWindow(PanelWindow);
  1726.                     }
  1727.                 }
  1728.             }
  1729.             while(!Done);
  1730.  
  1731.             PopWindow();
  1732.         }
  1733.  
  1734.         LT_DeleteHandle(Handle);
  1735.     }
  1736.  
  1737.     return(Success);
  1738. }
  1739.  
  1740.     /* WakeUp(struct Window *Window,WORD Sound):
  1741.      *
  1742.      *    Pop a window to the front and alert the user.
  1743.      */
  1744.  
  1745. VOID __regargs
  1746. WakeUp(struct Window *Window,WORD Sound)
  1747. {
  1748.     if(Window)
  1749.     {
  1750.         if(Config -> MiscConfig -> AlertMode == ALERT_SCREEN || Config -> MiscConfig -> AlertMode == ALERT_BEEP_SCREEN)
  1751.         {
  1752.             if(Window -> WScreen -> LeftEdge > 0)
  1753.             {
  1754.                 if(Window -> WScreen -> TopEdge > 0)
  1755.                     MoveScreen(Window -> WScreen,-Window -> WScreen -> LeftEdge,-Window -> WScreen -> TopEdge);
  1756.                 else
  1757.                     MoveScreen(Window -> WScreen,-Window -> WScreen -> LeftEdge,0);
  1758.             }
  1759.             else
  1760.             {
  1761.                 if(Window -> WScreen -> TopEdge > 0)
  1762.                     MoveScreen(Window -> WScreen,0,-Window -> WScreen -> TopEdge);
  1763.             }
  1764.  
  1765.             WindowToFront(Window);
  1766.  
  1767.             ScreenToFront(Window -> WScreen);
  1768.         }
  1769.     }
  1770.  
  1771.     if(Sound != SOUND_BELL || Config -> MiscConfig -> AlertMode == ALERT_BEEP || Config -> MiscConfig -> AlertMode == ALERT_BEEP_SCREEN)
  1772.         SoundPlay(Sound);
  1773. }
  1774.  
  1775.     /* TaskDestructor(struct DataMsg *Item):
  1776.      *
  1777.      *    Msg destructor for the routines below.
  1778.      */
  1779.  
  1780. STATIC VOID __stdargs
  1781. TaskDestructor(struct DataMsg *Item)
  1782. {
  1783.     Signal((struct Process *)Item -> Data,SIGBREAKF_CTRL_F);
  1784. }
  1785.  
  1786.     /* AmigaDOSBackgroundServer(VOID):
  1787.      *
  1788.      *    Background process to handle tool execution.
  1789.      */
  1790.  
  1791. STATIC VOID __saveds
  1792. AmigaDOSBackgroundServer(VOID)
  1793. {
  1794.     BPTR         OldCOS,
  1795.              NewCOS = NULL;
  1796.     struct DataMsg     Msg;
  1797.     STRPTR         Command;
  1798.     struct Process    *Me;
  1799.  
  1800.         /* Look who we are. */
  1801.  
  1802.     Me = (struct Process *)SysBase -> ThisTask;
  1803.  
  1804.     Command = Me -> pr_Task . tc_UserData;
  1805.  
  1806.         /* Create console output stream, will be closed automagically on exit. */
  1807.  
  1808.     if(!Me -> pr_COS && Me -> pr_ConsoleTask)
  1809.     {
  1810.         if(NewCOS = Open("*",MODE_NEWFILE))
  1811.         {
  1812.             OldCOS = Me -> pr_COS;
  1813.  
  1814.             Me -> pr_COS = NewCOS;
  1815.         }
  1816.     }
  1817.  
  1818.     SystemTags(Command,
  1819.         SYS_UserShell,    TRUE,
  1820.     TAG_DONE);
  1821.  
  1822.     FreeVecPooled(Command);
  1823.  
  1824.     Forbid();
  1825.  
  1826.     InitMsgItem(&Msg,TaskDestructor);
  1827.  
  1828.     Msg . Type = DATAMSGTYPE_COMMANDDONE;
  1829.     Msg . Data = (UBYTE *)Me;
  1830.  
  1831.     ClrSignal(SIGBREAKF_CTRL_F);
  1832.  
  1833.     PutMsgItem(SpecialQueue,(struct MsgItem *)&Msg);
  1834.  
  1835.     Wait(SIGBREAKF_CTRL_F);
  1836.  
  1837.     if(NewCOS)
  1838.     {
  1839.         Me -> pr_COS = OldCOS;
  1840.  
  1841.         Close(NewCOS);
  1842.     }
  1843. }
  1844.  
  1845.     /* SendAmigaDOSCommand(STRPTR Name):
  1846.      *
  1847.      *    Let the current default Shell execute an AmigaDOS
  1848.      *    command. Block until the command has returned.
  1849.      */
  1850.  
  1851. VOID __regargs
  1852. SendAmigaDOSCommand(STRPTR Name)
  1853. {
  1854.     STRPTR NewName;
  1855.  
  1856.     if(NewName = (STRPTR)AllocVecPooled(strlen(Name) + 1 + 256,MEMF_ANY))
  1857.     {
  1858.         struct Process    *NewProcess;
  1859.         BPTR         Stream;
  1860.         STRPTR         NewWindowName;
  1861.  
  1862.         strcpy(NewName,Name);
  1863.  
  1864.         NewWindowName = NewName + strlen(NewName) + 1;
  1865.  
  1866.         BlockWindows();
  1867.  
  1868.         SetQueueDiscard(SpecialQueue,FALSE);
  1869.  
  1870.             /* Open the output file. */
  1871.  
  1872.         if(WindowName[0])
  1873.         {
  1874.             UBYTE LocalName[MAXPUBSCREENNAME + 1];
  1875.  
  1876.             if(Window)
  1877.             {
  1878.                 if(!GetPubScreenName(Window -> WScreen,LocalName))
  1879.                     LocalName[0] = 0;
  1880.             }
  1881.  
  1882.             if(LocalName[0])
  1883.             {
  1884.                 SPrintf(NewWindowName,WindowName,LocalName);
  1885.  
  1886.                 Stream = Open(NewWindowName,MODE_NEWFILE);
  1887.             }
  1888.             else
  1889.                 Stream = Open(WindowName,MODE_NEWFILE);
  1890.         }
  1891.         else
  1892.             Stream = NULL;
  1893.  
  1894.         Forbid();
  1895.  
  1896.         if(Stream)
  1897.         {
  1898.             if(GoodStream(Stream))
  1899.             {
  1900.                 struct FileHandle *Handle = (struct FileHandle *)BADDR(Stream);
  1901.  
  1902.                 NewProcess = (struct Process *)CreateNewProcTags(
  1903.                     NP_Entry,    AmigaDOSBackgroundServer,
  1904.                     NP_Name,    "term AmigaDOS Background Process",
  1905.                     NP_Input,    Stream,
  1906.                     NP_Output,    NULL,
  1907.                     NP_Cli,        TRUE,
  1908.                     NP_ConsoleTask,    Handle -> fh_Type,
  1909.                     NP_StackSize,    16384,
  1910.                 TAG_END);
  1911.             }
  1912.             else
  1913.             {
  1914.                 NewProcess = (struct Process *)CreateNewProcTags(
  1915.                     NP_Entry,    AmigaDOSBackgroundServer,
  1916.                     NP_Name,    "term AmigaDOS Background Process",
  1917.                     NP_Output,    Stream,
  1918.                     NP_Cli,        TRUE,
  1919.                     NP_ConsoleTask,    NULL,
  1920.                     NP_StackSize,    16384,
  1921.                 TAG_END);
  1922.             }
  1923.         }
  1924.         else
  1925.         {
  1926.             NewProcess = (struct Process *)CreateNewProcTags(
  1927.                 NP_Entry,    AmigaDOSBackgroundServer,
  1928.                 NP_Name,    "term AmigaDOS Background Process",
  1929.                 NP_Cli,        TRUE,
  1930.                 NP_ConsoleTask,    NULL,
  1931.                 NP_StackSize,    16384,
  1932.             TAG_END);
  1933.         }
  1934.  
  1935.             /* Did we succeed in creating the process? */
  1936.  
  1937.         if(NewProcess)
  1938.         {
  1939.             CantQuit++;
  1940.  
  1941.             NewProcess -> pr_Task . tc_UserData = NewName;
  1942.  
  1943.             Permit();
  1944.         }
  1945.         else
  1946.         {
  1947.             Permit();
  1948.  
  1949.             if(Stream)
  1950.                 Close(Stream);
  1951.  
  1952.             FreeVecPooled(NewName);
  1953.  
  1954.             BumpWindow(Window);
  1955.  
  1956.             ReleaseWindows();
  1957.         }
  1958.     }
  1959. }
  1960.  
  1961.     /* RexxBackgroundServer():
  1962.      *
  1963.      *    The background process to handle the rexx
  1964.      *    massaging.
  1965.      */
  1966.  
  1967. STATIC VOID __saveds
  1968. RexxBackgroundServer(VOID)
  1969. {
  1970.     struct MsgPort     *RexxPort;
  1971.     BPTR         OldCOS,
  1972.              NewCOS = NULL;
  1973.     struct DataMsg     Msg;
  1974.     STRPTR         Command;
  1975.     struct Process    *Me;
  1976.  
  1977.         /* Look who we are. */
  1978.  
  1979.     Me = (struct Process *)SysBase -> ThisTask;
  1980.  
  1981.     Command = Me -> pr_Task . tc_UserData;
  1982.  
  1983.         /* Create console output stream, will be closed automagically on exit. */
  1984.  
  1985.     if(!Me -> pr_COS && Me -> pr_ConsoleTask)
  1986.     {
  1987.         if(NewCOS = Open("*",MODE_NEWFILE))
  1988.         {
  1989.             OldCOS = Me -> pr_COS;
  1990.  
  1991.             Me -> pr_COS = NewCOS;
  1992.         }
  1993.     }
  1994.  
  1995.     if(RexxPort = FindPort(RXSDIR))
  1996.     {
  1997.         struct MsgPort __aligned     ReplyPort;
  1998.         struct RexxMsg            *RexxMsg;
  1999.  
  2000.         InitSinglePort(&ReplyPort);
  2001.  
  2002.         if(RexxMsg = CreateRexxMsg(&ReplyPort,"term",RexxPortName))
  2003.         {
  2004.             if(RexxMsg -> rm_Args[0] = CreateArgstring(Command,strlen(Command)))
  2005.             {
  2006.                 RexxMsg -> rm_Action = RXCOMM;
  2007.  
  2008.                 Forbid();
  2009.  
  2010.                 ClrSignal(SIGF_SINGLE);
  2011.  
  2012.                 PutMsg(RexxPort,(struct Message *)RexxMsg);
  2013.  
  2014.                 WaitPort(&ReplyPort);
  2015.  
  2016.                 GetMsg(&ReplyPort);
  2017.  
  2018.                 Permit();
  2019.  
  2020.                     /* This doesn't look too
  2021.                      * good, does it?
  2022.                      */
  2023.  
  2024.                 if(RexxMsg -> rm_Result1 && Me -> pr_COS)
  2025.                     Printf(LocaleString(MSG_TERMAUX_COMMAND_HAS_TERMINATED_TXT),Command,RexxMsg -> rm_Result1,RexxMsg -> rm_Result2);
  2026.  
  2027.                 DeleteArgstring(RexxMsg -> rm_Args[0]);
  2028.             }
  2029.  
  2030.             DeleteRexxMsg(RexxMsg);
  2031.         }
  2032.     }
  2033.  
  2034.     FreeVecPooled(Command);
  2035.  
  2036.     Forbid();
  2037.  
  2038.     InitMsgItem(&Msg,TaskDestructor);
  2039.  
  2040.     Msg . Type = DATAMSGTYPE_COMMANDDONE;
  2041.     Msg . Data = (UBYTE *)Me;
  2042.  
  2043.     ClrSignal(SIGBREAKF_CTRL_F);
  2044.  
  2045.     PutMsgItem(SpecialQueue,(struct MsgItem *)&Msg);
  2046.  
  2047.     Wait(SIGBREAKF_CTRL_F);
  2048.  
  2049.     if(NewCOS)
  2050.     {
  2051.         Me -> pr_COS = OldCOS;
  2052.  
  2053.         Close(NewCOS);
  2054.     }
  2055. }
  2056.  
  2057.     /* SendARexxCommand(STRPTR Name,BOOL QueueIt):
  2058.      *
  2059.      *    Let the ARexx server execute a command (or a script
  2060.      *    file if necessary) and block until the command
  2061.      *    has returned.
  2062.      */
  2063.  
  2064. VOID __regargs
  2065. SendARexxCommand(STRPTR Name,BOOL QueueIt)
  2066. {
  2067.     STRPTR NewName;
  2068.  
  2069.     if(QueueIt)
  2070.     {
  2071.         ObtainSemaphore(&ARexxQueueSemaphore);
  2072.  
  2073.         if(ARexxRunning)
  2074.         {
  2075.             struct Node *Node;
  2076.  
  2077.             if(Node = CreateNode(Name))
  2078.                 AddTail(&ARexxQueue,Node);
  2079.  
  2080.             ReleaseSemaphore(&ARexxQueueSemaphore);
  2081.  
  2082.             return;
  2083.         }
  2084.     }
  2085.  
  2086.     if(NewName = (STRPTR)AllocVecPooled(strlen(Name) + 1 + 256,MEMF_ANY))
  2087.     {
  2088.         struct Process    *NewProcess;
  2089.         BPTR         Stream;
  2090.         STRPTR         NewWindowName;
  2091.  
  2092.         strcpy(NewName,Name);
  2093.  
  2094.         NewWindowName = NewName + strlen(NewName) + 1;
  2095.  
  2096.         BlockWindows();
  2097.  
  2098.         SetQueueDiscard(SpecialQueue,FALSE);
  2099.  
  2100.             /* Open the output file. */
  2101.  
  2102.         if(WindowName[0])
  2103.         {
  2104.             UBYTE LocalName[MAXPUBSCREENNAME + 1];
  2105.  
  2106.             if(Window)
  2107.             {
  2108.                 if(!GetPubScreenName(Window -> WScreen,LocalName))
  2109.                     LocalName[0] = 0;
  2110.             }
  2111.  
  2112.             if(LocalName[0])
  2113.             {
  2114.                 SPrintf(NewWindowName,WindowName,LocalName);
  2115.  
  2116.                 Stream = Open(NewWindowName,MODE_NEWFILE);
  2117.             }
  2118.             else
  2119.                 Stream = Open(WindowName,MODE_NEWFILE);
  2120.         }
  2121.         else
  2122.             Stream = NULL;
  2123.  
  2124.         Forbid();
  2125.  
  2126.             /* Create the background process which will
  2127.              * handle all the messy rexx message sending
  2128.              * for us.
  2129.              */
  2130.  
  2131.         if(Stream)
  2132.         {
  2133.             if(GoodStream(Stream))
  2134.             {
  2135.                 struct FileHandle *Handle = (struct FileHandle *)BADDR(Stream);
  2136.  
  2137.                 NewProcess = (struct Process *)CreateNewProcTags(
  2138.                     NP_Entry,    RexxBackgroundServer,
  2139.                     NP_Name,    "term ARexx Background Process",
  2140.                     NP_Input,    Stream,
  2141.                     NP_Output,    NULL,
  2142.                     NP_Cli,        TRUE,
  2143.                     NP_ConsoleTask,    Handle -> fh_Type,
  2144.                     NP_StackSize,    16384,
  2145.                 TAG_END);
  2146.             }
  2147.             else
  2148.             {
  2149.                 NewProcess = (struct Process *)CreateNewProcTags(
  2150.                     NP_Entry,    RexxBackgroundServer,
  2151.                     NP_Name,    "term ARexx Background Process",
  2152.                     NP_Output,    Stream,
  2153.                     NP_Cli,        TRUE,
  2154.                     NP_ConsoleTask,    NULL,
  2155.                     NP_StackSize,    16384,
  2156.                 TAG_END);
  2157.             }
  2158.         }
  2159.         else
  2160.         {
  2161.             NewProcess = (struct Process *)CreateNewProcTags(
  2162.                 NP_Entry,    RexxBackgroundServer,
  2163.                 NP_Name,    "term ARexx Background Process",
  2164.                 NP_Cli,        TRUE,
  2165.                 NP_ConsoleTask,    NULL,
  2166.                 NP_StackSize,    16384,
  2167.             TAG_END);
  2168.         }
  2169.  
  2170.             /* Did we succeed in creating the process? */
  2171.  
  2172.         if(NewProcess)
  2173.         {
  2174.             CantQuit++;
  2175.  
  2176.             NewProcess -> pr_Task . tc_UserData = NewName;
  2177.  
  2178.             Permit();
  2179.  
  2180.             if(QueueIt)
  2181.                 ARexxRunning = TRUE;
  2182.         }
  2183.         else
  2184.         {
  2185.             Permit();
  2186.  
  2187.             if(Stream)
  2188.                 Close(Stream);
  2189.  
  2190.             FreeVecPooled(NewName);
  2191.  
  2192.             BumpWindow(Window);
  2193.  
  2194.             ReleaseWindows();
  2195.         }
  2196.     }
  2197.  
  2198.     if(QueueIt)
  2199.         ReleaseSemaphore(&ARexxQueueSemaphore);
  2200. }
  2201.  
  2202.     /* BlockWindows():
  2203.      *
  2204.      *    Block the main window and the status window (i.e. disable
  2205.      *    the menu and attach a wait pointer).
  2206.      */
  2207.  
  2208. VOID
  2209. BlockWindows()
  2210. {
  2211.     if(!(BlockNestCount++))
  2212.     {
  2213.         LT_LockWindow(Window);
  2214.         LT_LockWindow(StatusWindow);
  2215.         LT_LockWindow(FastWindow);
  2216.  
  2217.         WeAreBlocking = TRUE;
  2218.  
  2219.         SetQueueDiscard(SpecialQueue,TRUE);
  2220.  
  2221.         GhostCursor();
  2222.     }
  2223. }
  2224.  
  2225.     /* ReleaseWindows():
  2226.      *
  2227.      *    Reenable the menus and clear the wait pointer.
  2228.      */
  2229.  
  2230. VOID
  2231. ReleaseWindows()
  2232. {
  2233.     if(BlockNestCount == 1)
  2234.     {
  2235.         LT_UnlockWindow(Window);
  2236.         LT_UnlockWindow(StatusWindow);
  2237.         LT_UnlockWindow(FastWindow);
  2238.  
  2239.         WeAreBlocking = FALSE;
  2240.  
  2241.         SetQueueDiscard(SpecialQueue,FALSE);
  2242.  
  2243.         if(Window)
  2244.         {
  2245.             Forbid();
  2246.  
  2247.             if(Window -> Flags & WFLG_WINDOWACTIVE)
  2248.                 NormalCursor();
  2249.  
  2250.             Permit();
  2251.         }
  2252.     }
  2253.  
  2254.     if(BlockNestCount)
  2255.         BlockNestCount--;
  2256. }
  2257.  
  2258.     /* LineRead(BPTR File,STRPTR Buffer,LONG MaxChars):
  2259.      *
  2260.      *    Read a few bytes from a file (à la gets).
  2261.      */
  2262.  
  2263. LONG __regargs
  2264. LineRead(BPTR File,STRPTR Buffer,LONG MaxChars)
  2265. {
  2266.     STATIC UBYTE __far    Data[1024];
  2267.     STATIC LONG        ReadIndex    = 0,
  2268.                 ReadLen        = 0;
  2269.  
  2270.     if(File)
  2271.     {
  2272.         LONG BytesRead = 0,i;
  2273.  
  2274.         for(i = 0 ; i < MaxChars ; i++)
  2275.         {
  2276.             if(ReadIndex >= ReadLen)
  2277.             {
  2278.                 ReadLen = Read(File,Data,1024);
  2279.  
  2280.                 ReadIndex = 0;
  2281.  
  2282.                 if(ReadLen <= 0)
  2283.                 {
  2284.                     Buffer[i] = 0;
  2285.  
  2286.                     return(BytesRead);
  2287.                 }
  2288.             }
  2289.  
  2290.             BytesRead++;
  2291.  
  2292.             if((Buffer[i] = Data[ReadIndex++]) == '\n')
  2293.             {
  2294.                 Buffer[i + 1] = 0;
  2295.  
  2296.                 return(BytesRead);
  2297.             }
  2298.         }
  2299.  
  2300.         return(BytesRead);
  2301.     }
  2302.     else
  2303.         ReadIndex = ReadLen = 0;
  2304. }
  2305.  
  2306.     /* GetBaudRate(STRPTR Buffer):
  2307.      *
  2308.      *    Calculate the baud rate contained in a connect string.
  2309.      */
  2310.  
  2311. LONG __regargs
  2312. GetBaudRate(STRPTR Buffer)
  2313. {
  2314.     LONG Rate,i,j;
  2315.  
  2316.     for(i = j = 0 ; i < strlen(Buffer) ; i++)
  2317.     {
  2318.         if(Buffer[i] == ' ')
  2319.             continue;
  2320.         else
  2321.         {
  2322.             if(Buffer[i] >= '0' && Buffer[i] <= '9')
  2323.                 SharedBuffer[j++] = Buffer[i];
  2324.             else
  2325.                 break;
  2326.         }
  2327.     }
  2328.  
  2329.     SharedBuffer[j] = 0;
  2330.  
  2331.     if(StrToLong(SharedBuffer,&Rate) > 0)
  2332.     {
  2333.         if(Rate > 0)
  2334.             return(Rate);
  2335.     }
  2336.  
  2337.     return(0);
  2338. }
  2339.  
  2340.     /* LookForIt(struct MenuItem *Item,ULONG ID):
  2341.      *
  2342.      *    Auxilary routine for FindThisItem(), scans
  2343.      *    menu item and sub item lists.
  2344.      */
  2345.  
  2346. STATIC struct MenuItem * __inline
  2347. LookForIt(struct MenuItem *Item,ULONG ID)
  2348. {
  2349.     while(Item)
  2350.     {
  2351.         if((ULONG)GTMENUITEM_USERDATA(Item) == ID)
  2352.             return(Item);
  2353.         else
  2354.         {
  2355.             if(Item -> SubItem)
  2356.             {
  2357.                 register struct MenuItem *TheItem;
  2358.  
  2359.                 if(TheItem = LookForIt(Item -> SubItem,ID))
  2360.                     return(TheItem);
  2361.             }
  2362.  
  2363.             Item = Item -> NextItem;
  2364.         }
  2365.     }
  2366.  
  2367.     return(NULL);
  2368. }
  2369.  
  2370.     /* FindThisItem(struct Menu *FirstMenu,ULONG MenuID):
  2371.      *
  2372.      *    Scan a menu for a menuitem associated with a
  2373.      *    menu ID.
  2374.      */
  2375.  
  2376. struct MenuItem * __regargs
  2377. FindThisItem(struct Menu *FirstMenu,ULONG MenuID)
  2378. {
  2379.     if(TypeOfMem(FirstMenu))
  2380.     {
  2381.         struct MenuItem *Item;
  2382.  
  2383.         while(FirstMenu)
  2384.         {
  2385.             if(Item = LookForIt(FirstMenu -> FirstItem,MenuID))
  2386.                 return(Item);
  2387.             else
  2388.                 FirstMenu = FirstMenu -> NextMenu;
  2389.         }
  2390.     }
  2391.  
  2392.     return(NULL);
  2393. }
  2394.  
  2395. struct Menu * __regargs
  2396. FindThisMenu(struct Menu *FirstMenu,ULONG MenuID)
  2397. {
  2398.     if(TypeOfMem(FirstMenu))
  2399.     {
  2400.         while(FirstMenu)
  2401.         {
  2402.             if(GTMENU_USERDATA(FirstMenu) == (APTR)MenuID)
  2403.                 return(FirstMenu);
  2404.             else
  2405.                 FirstMenu = FirstMenu -> NextMenu;
  2406.         }
  2407.     }
  2408.  
  2409.     return(NULL);
  2410. }
  2411.  
  2412.     /* GetItem(ULONG MenuID):
  2413.      *
  2414.      *    Get the checkmark state of a menu item.
  2415.      */
  2416.  
  2417. BYTE __regargs
  2418. GetItem(ULONG MenuID)
  2419. {
  2420.     if(Menu)
  2421.     {
  2422.         struct MenuItem *Item;
  2423.  
  2424.         if(Item = FindThisItem(Menu,MenuID))
  2425.         {
  2426.             if(Item -> Flags & CHECKED)
  2427.                 return(TRUE);
  2428.         }
  2429.     }
  2430.  
  2431.     return(FALSE);
  2432. }
  2433.  
  2434.     /* SetItem(ULONG MenuID,BYTE Mode):
  2435.      *
  2436.      *    Clear or set the checkmark or state of a menu item.
  2437.      */
  2438.  
  2439. VOID __regargs
  2440. SetItem(ULONG MenuID,BYTE Mode)
  2441. {
  2442.         /* Is the global pull-down menu available? */
  2443.  
  2444.     if(Menu)
  2445.     {
  2446.         struct MenuItem    *Item;
  2447.         struct Menu    *ThisMenu;
  2448.  
  2449.         if(ThisMenu = FindThisMenu(Menu,MenuID))
  2450.         {
  2451.                 /* Remove the menu from the windows. */
  2452.  
  2453.             if(Window)
  2454.                 ClearMenuStrip(Window);
  2455.  
  2456.             if(StatusWindow)
  2457.                 ClearMenuStrip(StatusWindow);
  2458.  
  2459.             if(FastWindow)
  2460.                 ClearMenuStrip(FastWindow);
  2461.  
  2462.             switch(Mode)
  2463.             {
  2464.                 case SETITEM_ON:
  2465.  
  2466.                     ThisMenu -> Flags |= MENUENABLED;
  2467.                     break;
  2468.  
  2469.                 case SETITEM_OFF:
  2470.  
  2471.                     ThisMenu -> Flags &= ~MENUENABLED;
  2472.                     break;
  2473.             }
  2474.  
  2475.                 /* Reattach the menu to the windows. */
  2476.  
  2477.             if(Window)
  2478.                 ResetMenuStrip(Window,Menu);
  2479.  
  2480.             if(StatusWindow)
  2481.                 ResetMenuStrip(StatusWindow,Menu);
  2482.  
  2483.             if(FastWindow)
  2484.                 ResetMenuStrip(FastWindow,Menu);
  2485.  
  2486.             return;
  2487.         }
  2488.  
  2489.             /* Try to find the menu item and change
  2490.              * the state of the checkmark.
  2491.              */
  2492.  
  2493.         if(Item = FindThisItem(Menu,MenuID))
  2494.         {
  2495.                 /* Remove the menu from the windows. */
  2496.  
  2497.             if(Window)
  2498.                 ClearMenuStrip(Window);
  2499.  
  2500.             if(StatusWindow)
  2501.                 ClearMenuStrip(StatusWindow);
  2502.  
  2503.             if(FastWindow)
  2504.                 ClearMenuStrip(FastWindow);
  2505.  
  2506.             switch(Mode)
  2507.             {
  2508.                 case SETITEM_SETCHECK:
  2509.  
  2510.                     Item -> Flags |= CHECKED;
  2511.                     break;
  2512.  
  2513.                 case SETITEM_CLRCHECK:
  2514.  
  2515.                     Item -> Flags &= ~CHECKED;
  2516.                     break;
  2517.  
  2518.                 case SETITEM_ON:
  2519.  
  2520.                     Item -> Flags |= ITEMENABLED;
  2521.                     break;
  2522.  
  2523.                 case SETITEM_OFF:
  2524.  
  2525.                     Item -> Flags &= ~ITEMENABLED;
  2526.                     break;
  2527.             }
  2528.  
  2529.                 /* Reattach the menu to the windows. */
  2530.  
  2531.             if(Window)
  2532.                 ResetMenuStrip(Window,Menu);
  2533.  
  2534.             if(StatusWindow)
  2535.                 ResetMenuStrip(StatusWindow,Menu);
  2536.  
  2537.             if(FastWindow)
  2538.                 ResetMenuStrip(FastWindow,Menu);
  2539.         }
  2540.     }
  2541. }
  2542.  
  2543.     /* GetFileSize(STRPTR Name):
  2544.      *
  2545.      *    Simple routine to return the size of a file in
  2546.      *    bytes.
  2547.      */
  2548.  
  2549. LONG __regargs
  2550. GetFileSize(STRPTR Name)
  2551. {
  2552.     struct FileInfoBlock    *FileInfo;
  2553.     LONG             FileSize = 0;
  2554.  
  2555.     if(FileInfo = (struct FileInfoBlock *)AllocDosObject(DOS_FIB,TAG_DONE))
  2556.     {
  2557.         BPTR FileLock;
  2558.  
  2559.         if(FileLock = Lock(Name,ACCESS_READ))
  2560.         {
  2561.             if(Examine(FileLock,FileInfo))
  2562.             {
  2563.                 if(FileInfo -> fib_DirEntryType < 0)
  2564.                     FileSize = FileInfo -> fib_Size;
  2565.             }
  2566.  
  2567.             UnLock(FileLock);
  2568.         }
  2569.  
  2570.         FreeDosObject(DOS_FIB,FileInfo);
  2571.     }
  2572.  
  2573.     return(FileSize);
  2574. }
  2575.  
  2576.     /* PutDimensionTags(struct Window *Reference,LONG Left,LONG Top,LONG Width,LONG Height):
  2577.      *
  2578.      *    Put back the default values for the requesters to open.
  2579.      */
  2580.  
  2581. VOID __regargs
  2582. PutDimensionTags(struct Window *Reference,LONG Left,LONG Top,LONG Width,LONG Height)
  2583. {
  2584.     if(Config -> MiscConfig -> RequesterMode != REQUESTERMODE_IGNORE && (!Config -> MiscConfig -> RequesterWidth || !Config -> MiscConfig -> RequesterHeight))
  2585.     {
  2586.         if(!Reference)
  2587.             Reference = Window;
  2588.  
  2589.         Config -> MiscConfig -> RequesterLeft    = Left    - Reference -> LeftEdge;
  2590.         Config -> MiscConfig -> RequesterTop    = Top    - Reference -> TopEdge;
  2591.         Config -> MiscConfig -> RequesterWidth    = Width;
  2592.         Config -> MiscConfig -> RequesterHeight    = Height;
  2593.     }
  2594. }
  2595.  
  2596.     /* GetDimensionTags(struct Window *Reference,struct TagItem *Tags):
  2597.      *
  2598.      *    Fills an array of tagitems with the dimensions of an asl requester
  2599.      *    to be opened.
  2600.      */
  2601.  
  2602. struct TagItem * __regargs
  2603. GetDimensionTags(struct Window *Reference,struct TagItem *Tags)
  2604. {
  2605.     if(Config -> MiscConfig -> RequesterMode == REQUESTERMODE_IGNORE || !Config -> MiscConfig -> RequesterWidth || !Config -> MiscConfig -> RequesterHeight)
  2606.     {
  2607.         STATIC ULONG Done = TAG_DONE;
  2608.  
  2609.         return((struct TagItem *)&Done);
  2610.     }
  2611.     else
  2612.     {
  2613.         LONG Left,Top,Width,Height;
  2614.  
  2615.         if(!Reference)
  2616.             Reference = Window;
  2617.  
  2618.         if(Config -> MiscConfig -> RequesterMode == REQUESTERMODE_CENTRE)
  2619.         {
  2620.             Left    = Reference -> LeftEdge    + (Reference -> Width - Config -> MiscConfig -> RequesterWidth) / 2;
  2621.             Top    = Reference -> TopEdge    + (Reference -> Height - Config -> MiscConfig -> RequesterHeight) / 2;
  2622.         }
  2623.         else
  2624.         {
  2625.             Left    = Config -> MiscConfig -> RequesterLeft    + Reference -> LeftEdge;
  2626.             Top    = Config -> MiscConfig -> RequesterTop    + Reference -> TopEdge;
  2627.         }
  2628.  
  2629.         Width    = Config -> MiscConfig -> RequesterWidth;
  2630.         Height    = Config -> MiscConfig -> RequesterHeight;
  2631.  
  2632.         Tags[0] . ti_Tag    = ASL_LeftEdge;
  2633.         Tags[0] . ti_Data    = Left;
  2634.         Tags[1] . ti_Tag    = ASL_TopEdge;
  2635.         Tags[1] . ti_Data    = Top;
  2636.         Tags[2] . ti_Tag    = ASL_Width;
  2637.         Tags[2] . ti_Data    = Width;
  2638.         Tags[3] . ti_Tag    = ASL_Height;
  2639.         Tags[3] . ti_Data    = Height;
  2640.         Tags[4] . ti_Data    = TAG_DONE;
  2641.  
  2642.         return(Tags);
  2643.     }
  2644. }
  2645.  
  2646.     /* GetFile(STRPTR Title,STRPTR Directory,STRPTR Name,STRPTR Buffer,STRPTR Pattern,BYTE SaveFlag,BYTE MultiSelect):
  2647.      *
  2648.      *    Call the asl.library file requester to select a single or
  2649.      *    a couple of files.
  2650.      */
  2651.  
  2652. struct FileRequester * __regargs
  2653. GetFile(struct Window *Parent,STRPTR Title,STRPTR Directory,STRPTR Name,STRPTR Buffer,STRPTR Pattern,BYTE SaveFlag,BYTE MultiSelect,BYTE DirsOnly,STRPTR OKText,BYTE AskWrite)
  2654. {
  2655.     STATIC UBYTE __far     DirBuffer[MAX_FILENAME_LENGTH],
  2656.                  PatternBuffer[60];
  2657.  
  2658.     struct FileRequester    *AslFileRequest;
  2659.     BYTE             Result        = FALSE,
  2660.                  DefaultPattern    = FALSE;
  2661.     LONG             Flags,ExtFlags = 0;
  2662.     WORD             i,j;
  2663.  
  2664.     UBYTE             OtherTitle[60];
  2665.     struct TagItem         DimensionTags[5];
  2666.  
  2667.     if(!Config -> MiscConfig -> ProtectiveMode)
  2668.         AskWrite = FALSE;
  2669.  
  2670.     if(!Parent)
  2671.         Parent = Window;
  2672.  
  2673.     for(i = j = 0 ; i < strlen(Title) ; i++)
  2674.     {
  2675.         if(Title[i] != '_')
  2676.             OtherTitle[j++] = Title[i];
  2677.     }
  2678.  
  2679.     OtherTitle[j] = 0;
  2680.  
  2681.     Title = OtherTitle;
  2682.  
  2683.     if(DirsOnly)
  2684.     {
  2685.         ExtFlags |= FIL1F_NOFILES;
  2686.  
  2687.         if(Pattern)
  2688.             ExtFlags |= FIL1F_MATCHDIRS;
  2689.     }
  2690.  
  2691.         /* Empty directory string? Revert to the last directory
  2692.          * name.
  2693.          */
  2694.  
  2695.     Forbid();
  2696.  
  2697.     if(!Directory[0])
  2698.     {
  2699.         if(!DirBuffer[0])
  2700.         {
  2701.             UBYTE LocalBuffer[MAX_FILENAME_LENGTH];
  2702.  
  2703.             if(!GetCurrentDirName(LocalBuffer,MAX_FILENAME_LENGTH))
  2704.                 LocalBuffer[0] = 0;
  2705.  
  2706.             if(!DirBuffer[0])
  2707.                 strcpy(DirBuffer,LocalBuffer);
  2708.         }
  2709.  
  2710.         Directory = DirBuffer;
  2711.     }
  2712.  
  2713.         /* If a wildcard pattern is required, add a gadget
  2714.          * to display it.
  2715.          */
  2716.  
  2717.     if(Pattern)
  2718.     {
  2719.         Flags = FILF_PATGAD;
  2720.  
  2721.         if(!Pattern[0])
  2722.         {
  2723.             DefaultPattern = TRUE;
  2724.  
  2725.             if(PatternBuffer[0])
  2726.                 Pattern = PatternBuffer;
  2727.             else
  2728.                 Pattern = "#?";
  2729.         }
  2730.         else
  2731.         {
  2732.             if(!Stricmp(Pattern,"#?") || !Stricmp(Pattern,PatternBuffer))
  2733.             {
  2734.                 DefaultPattern = TRUE;
  2735.  
  2736.                 Pattern = PatternBuffer;
  2737.             }
  2738.         }
  2739.     }
  2740.     else
  2741.     {
  2742.         Flags = 0;
  2743.  
  2744.         Pattern = "#?";
  2745.     }
  2746.  
  2747.     Permit();
  2748.  
  2749.         /* Set the save flag if we are about to save something. */
  2750.  
  2751.     if(SaveFlag)
  2752.         Flags |= FILF_SAVE;
  2753.  
  2754.         /* Set the multiselect bit if multiple files are
  2755.          * to be selected (e.g. for batch file upload).
  2756.          */
  2757.  
  2758.     if(MultiSelect)
  2759.         Flags |= FILF_MULTISELECT;
  2760.  
  2761.         /* Provide a standard `Ok' text if none
  2762.          * specified.
  2763.          */
  2764.  
  2765.     if(!OKText)
  2766.         OKText = (SaveFlag ? LocaleString(MSG_GLOBAL_SAVE_TXT) : LocaleString(MSG_GLOBAL_OPEN_TXT));
  2767.  
  2768.         /* Allocate the asl.library directory requester
  2769.          * and display it.
  2770.          */
  2771.  
  2772.     if(AslFileRequest = (struct FileRequester *)AllocAslRequestTags(ASL_FileRequest,
  2773.         ASL_Window,    Parent,
  2774.         ASL_File,    Name,
  2775.         ASL_Dir,    Directory,
  2776.         Title ? ASL_Hail : TAG_IGNORE,    Title,
  2777.         ASL_FuncFlags,    Flags | FILF_NEWIDCMP,
  2778.         ASL_Pattern,    Pattern,
  2779.         ASL_OKText,    OKText,
  2780.         ASL_ExtFlags1,    ExtFlags,
  2781.         ASLFR_TextAttr,    &UserFont,
  2782.     TAG_MORE,GetDimensionTags(NULL,DimensionTags)))
  2783.     {
  2784.         if(AslRequestTags(AslFileRequest,TAG_DONE))
  2785.         {
  2786.             PutDimensionTags(NULL,AslFileRequest -> rf_LeftEdge,AslFileRequest -> rf_TopEdge,AslFileRequest -> rf_Width,AslFileRequest -> rf_Height);
  2787.  
  2788.             if(!DirsOnly)
  2789.             {
  2790.                 STRPTR FileName;
  2791.  
  2792.                 if(AslFileRequest -> rf_NumArgs > 1 && AslFileRequest -> rf_ArgList)
  2793.                     FileName = AslFileRequest -> rf_ArgList -> wa_Name;
  2794.                 else
  2795.                     FileName = AslFileRequest -> rf_File;
  2796.  
  2797.                     /* Do we have a valid file name? */
  2798.  
  2799.                 if(FileName)
  2800.                 {
  2801.                         /* Build a legal path/file string. */
  2802.  
  2803.                     strcpy(Buffer,AslFileRequest -> rf_Dir);
  2804.  
  2805.                     AddPart((STRPTR)Buffer,FileName,MAX_FILENAME_LENGTH);
  2806.  
  2807.                     Result = TRUE;
  2808.  
  2809.                     Forbid();
  2810.  
  2811.                     strcpy(DirBuffer,AslFileRequest -> rf_Dir);
  2812.  
  2813.                     Permit();
  2814.                 }
  2815.             }
  2816.             else
  2817.             {
  2818.                 if(AslFileRequest -> rf_Dir[0])
  2819.                 {
  2820.                     strcpy(Buffer,AslFileRequest -> rf_Dir);
  2821.  
  2822.                     Result = TRUE;
  2823.  
  2824.                     Forbid();
  2825.  
  2826.                     strcpy(DirBuffer,AslFileRequest -> rf_Dir);
  2827.  
  2828.                     Permit();
  2829.                 }
  2830.             }
  2831.         }
  2832.     }
  2833.  
  2834.         /* We didn't get a file, no need to keep the
  2835.          * file requester.
  2836.          */
  2837.  
  2838.     if(!Result && AslFileRequest)
  2839.     {
  2840.         FreeAslRequest(AslFileRequest);
  2841.  
  2842.         return(NULL);
  2843.     }
  2844.     else
  2845.     {
  2846.         if(SaveFlag && AskWrite)
  2847.         {
  2848.             if(GetFileSize(Buffer))
  2849.             {
  2850.                 if(!MyEasyRequest(Parent,LocaleString(MSG_GLOBAL_FILE_ALREADY_EXISTS_OVERWRITE_TXT),LocaleString(MSG_GLOBAL_REPLACE_CANCEL_TXT),FilePart(Buffer)))
  2851.                 {
  2852.                     FreeAslRequest(AslFileRequest);
  2853.  
  2854.                     return(NULL);
  2855.                 }
  2856.             }
  2857.         }
  2858.  
  2859.         Forbid();
  2860.  
  2861.         if(DefaultPattern)
  2862.             strcpy(PatternBuffer,AslFileRequest -> rf_Pat);
  2863.  
  2864.         Permit();
  2865.  
  2866.         return(AslFileRequest);
  2867.     }
  2868. }
  2869.  
  2870.     /* MyEasyRequest(struct Window *Window,STRPTR Text,STRPTR Gadgets,...):
  2871.      *
  2872.      *    Really quite simple varargs version of Intuition's
  2873.      *    EasyRequest requester.
  2874.      */
  2875.  
  2876. WORD __stdargs
  2877. MyEasyRequest(struct Window *Window,STRPTR Text,STRPTR Gadgets,...)
  2878. {
  2879.     struct EasyStruct    Easy;
  2880.     va_list            VarArgs;
  2881.     LONG            i,GadgetCount;
  2882.  
  2883.     for(i = GadgetCount = 0 ; i < strlen(Gadgets) ; i++)
  2884.     {
  2885.         if(Gadgets[i] == '|')
  2886.             GadgetCount++;
  2887.     }
  2888.  
  2889.         /* Standard data. */
  2890.  
  2891.     Easy . es_StructSize    = sizeof(struct EasyStruct);
  2892.     Easy . es_Flags        = NULL;
  2893.     Easy . es_Title        = LocaleString(MSG_TERMAUX_TERM_REQUEST_TXT);
  2894.     Easy . es_TextFormat    = Text;
  2895.     Easy . es_GadgetFormat    = Gadgets;
  2896.  
  2897.     if(GadgetCount)
  2898.     {
  2899.         WORD Result;
  2900.  
  2901.         if(GTLayoutBase)
  2902.             LT_LockWindow(Window);
  2903.  
  2904.             /* Use the argument array to build the
  2905.              * requester and display it.
  2906.              */
  2907.  
  2908.         va_start(VarArgs,Gadgets);
  2909.         Result = EasyRequestArgs(Window,&Easy,NULL,VarArgs);
  2910.         va_end(VarArgs);
  2911.  
  2912.         if(GTLayoutBase)
  2913.             LT_UnlockWindow(Window);
  2914.  
  2915.         return(Result);
  2916.     }
  2917.     else
  2918.     {
  2919.         struct Window *ReqWindow;
  2920.  
  2921.         if(GTLayoutBase)
  2922.             LT_LockWindow(Window);
  2923.  
  2924.         va_start(VarArgs,Gadgets);
  2925.  
  2926.         if(ReqWindow = BuildEasyRequestArgs(Window,&Easy,IDCMP_RAWKEY,VarArgs))
  2927.         {
  2928.             ULONG    IDCMP;
  2929.             LONG    Result;
  2930.  
  2931.             FOREVER
  2932.             {
  2933.                 WaitPort(ReqWindow -> UserPort);
  2934.  
  2935.                 IDCMP = NULL;
  2936.  
  2937.                 Result = SysReqHandler(ReqWindow,&IDCMP,FALSE);
  2938.  
  2939.                 if(!Result || (Result == -2 && !(IDCMP & IDCMP_RAWKEY)))
  2940.                     break;
  2941.             }
  2942.  
  2943.             FreeSysRequest(ReqWindow);
  2944.         }
  2945.  
  2946.         va_end(VarArgs);
  2947.  
  2948.         if(GTLayoutBase)
  2949.             LT_UnlockWindow(Window);
  2950.  
  2951.         return(0);
  2952.     }
  2953. }
  2954.  
  2955.     /* CloseWindowSafely(struct Window *Window):
  2956.      *
  2957.      *    Close a window freeing all messages pending at
  2958.      *    its user port (taken from example source code
  2959.      *    published once upon a time in Amiga Mail).
  2960.      */
  2961.  
  2962. VOID __regargs
  2963. CloseWindowSafely(struct Window *Window)
  2964. {
  2965.     struct IntuiMessage    *IntuiMessage;
  2966.     struct Node        *Successor;
  2967.  
  2968.     Forbid();
  2969.  
  2970.     IntuiMessage = (struct IntuiMessage *)Window -> UserPort -> mp_MsgList . lh_Head;
  2971.  
  2972.     while(Successor = IntuiMessage -> ExecMessage . mn_Node . ln_Succ)
  2973.     {
  2974.         if(IntuiMessage -> IDCMPWindow == Window)
  2975.         {
  2976.             Remove(IntuiMessage);
  2977.  
  2978.             ReplyMsg((struct Message *)IntuiMessage);
  2979.         }
  2980.  
  2981.         IntuiMessage = (struct IntuiMessage *)Successor;
  2982.     }
  2983.  
  2984.     Window -> UserPort = NULL;
  2985.  
  2986.     ModifyIDCMP(Window,NULL);
  2987.  
  2988.     Permit();
  2989.  
  2990.     LT_DeleteWindowLock(Window);
  2991.  
  2992.     CloseWindow(Window);
  2993. }
  2994.  
  2995.     /* WaitTime(LONG Secs,LONG Micros):
  2996.      *
  2997.      *    Wait a given period of time.
  2998.      */
  2999.  
  3000. VOID __regargs
  3001. WaitTime(LONG Secs,LONG Micros)
  3002. {
  3003.     TimeRequest -> tr_node . io_Command    = TR_ADDREQUEST;
  3004.     TimeRequest -> tr_time . tv_secs    = Secs;
  3005.     TimeRequest -> tr_time . tv_micro    = Micros;
  3006.  
  3007.     DoIO(TimeRequest);
  3008. }
  3009.  
  3010.     /* StopTime():
  3011.      *
  3012.      *    Stop the running timer.
  3013.      */
  3014.  
  3015. VOID
  3016. StopTime()
  3017. {
  3018.     if(TimerRunning)
  3019.     {
  3020.         if(!CheckIO(TimeRequest))
  3021.             AbortIO(TimeRequest);
  3022.  
  3023.         WaitIO(TimeRequest);
  3024.     }
  3025. }
  3026.  
  3027.     /* StartTime(LONG Secs,LONG Micros):
  3028.      *
  3029.      *    Start the timer asynchronously.
  3030.      */
  3031.  
  3032. VOID __regargs
  3033. StartTime(LONG Secs,LONG Micros)
  3034. {
  3035.     StopTime();
  3036.  
  3037.     TimeRequest -> tr_node . io_Command    = TR_ADDREQUEST;
  3038.     TimeRequest -> tr_time . tv_secs    = Secs;
  3039.     TimeRequest -> tr_time . tv_micro    = Micros;
  3040.  
  3041.     ClrSignal(SIG_TIMER);
  3042.  
  3043.     SendIO(TimeRequest);
  3044.  
  3045.     TimerRunning = TRUE;
  3046. }
  3047.  
  3048.     /* GetEnvDOS(STRPTR Name,STRPTR Buffer):
  3049.      *
  3050.      *    Get the contents of a vanilla AmigaDOS environment
  3051.      *    variable.
  3052.      */
  3053.  
  3054. STRPTR __regargs
  3055. GetEnvDOS(STRPTR Name,STRPTR Buffer)
  3056. {
  3057.     LONG    Size;
  3058.     BPTR    File,SomeLock;
  3059.  
  3060.     Buffer[0] = 0;
  3061.  
  3062.         /* Is ENV: present? */
  3063.  
  3064.     if(SomeLock = Lock("Env:",ACCESS_READ))
  3065.     {
  3066.         UBYTE SomeBuffer[MAX_FILENAME_LENGTH];
  3067.  
  3068.         UnLock(SomeLock);
  3069.  
  3070.         strcpy(SomeBuffer,"Env:");
  3071.         strcat(SomeBuffer,Name);
  3072.  
  3073.             /* Open the file. */
  3074.  
  3075.         if(File = Open(SomeBuffer,MODE_OLDFILE))
  3076.         {
  3077.                 /* Read the contents. */
  3078.  
  3079.             Size = Read(File,Buffer,256);
  3080.  
  3081.             Close(File);
  3082.  
  3083.             if(Size > 0)
  3084.             {
  3085.                 Buffer[Size] = 0;
  3086.  
  3087.                 return(Buffer);
  3088.             }
  3089.         }
  3090.     }
  3091.  
  3092.     return(NULL);
  3093. }
  3094.  
  3095.     /* SetEnvDOS(STRPTR Name,STRPTR Value):
  3096.      *
  3097.      *    Set the contents of a vanilla AmigaDOS environment
  3098.      *    variable.
  3099.      */
  3100.  
  3101. BYTE __regargs
  3102. SetEnvDOS(STRPTR Name,STRPTR Value)
  3103. {
  3104.     UBYTE    Buffer[MAX_FILENAME_LENGTH],*Destination;
  3105.     LONG    Length;
  3106.     BPTR    File,FileLock;
  3107.     BYTE    Success = TRUE;
  3108.     WORD    i;
  3109.  
  3110.     for(i = 0 ; i < 2 ; i++)
  3111.     {
  3112.         if(i)
  3113.             Destination = "EnvArc:";
  3114.         else
  3115.             Destination = "Env:";
  3116.  
  3117.             /* Is ENV:/ENVARC: present? */
  3118.  
  3119.         if(FileLock = Lock(Destination,ACCESS_READ))
  3120.         {
  3121.             UnLock(FileLock);
  3122.  
  3123.             strcpy(Buffer,Destination);
  3124.             strcat(Buffer,Name);
  3125.  
  3126.                 /* There already is a variable of that
  3127.                  * name in the environment storage
  3128.                  * directory.
  3129.                  */
  3130.  
  3131.             if(FileLock = Lock(Buffer,ACCESS_WRITE))
  3132.             {
  3133.                 UnLock(FileLock);
  3134.  
  3135.                     /* Delete the variable. */
  3136.  
  3137.                 if(!DeleteFile(Buffer))
  3138.                 {
  3139.                     Success = FALSE;
  3140.  
  3141.                     continue;
  3142.                 }
  3143.             }
  3144.  
  3145.                 /* Set the new variable. */
  3146.  
  3147.             if(Length = strlen(Value))
  3148.             {
  3149.                 if(File = Open(Buffer,MODE_NEWFILE))
  3150.                 {
  3151.                     if(Write(File,Value,Length) != Length)
  3152.                     {
  3153.                         Close(File);
  3154.  
  3155.                         DeleteFile(Buffer);
  3156.  
  3157.                         Success = FALSE;
  3158.                     }
  3159.                     else
  3160.                     {
  3161.                         Close(File);
  3162.  
  3163.                         AddProtection(Buffer,FIBF_EXECUTE);
  3164.                     }
  3165.                 }
  3166.                 else
  3167.                     Success = FALSE;
  3168.             }
  3169.         }
  3170.         else
  3171.             Success = FALSE;
  3172.     }
  3173.  
  3174.     return(Success);
  3175. }
  3176.  
  3177.     /* BumpWindow(struct Window *SomeWindow):
  3178.      *
  3179.      *    Bring a window to the front (and shift the screen
  3180.      *    back to its initial position).
  3181.      */
  3182.  
  3183. VOID __regargs
  3184. BumpWindow(struct Window *SomeWindow)
  3185. {
  3186.     if(SomeWindow)
  3187.     {
  3188.         if(SomeWindow -> WScreen -> LeftEdge > 0)
  3189.         {
  3190.             if(SomeWindow -> WScreen -> TopEdge > 0)
  3191.                 MoveScreen(SomeWindow -> WScreen,-SomeWindow -> WScreen -> LeftEdge,-SomeWindow -> WScreen -> TopEdge);
  3192.             else
  3193.                 MoveScreen(SomeWindow -> WScreen,-SomeWindow -> WScreen -> LeftEdge,0);
  3194.         }
  3195.         else
  3196.         {
  3197.             if(SomeWindow -> WScreen -> TopEdge > 0)
  3198.                 MoveScreen(SomeWindow -> WScreen,0,-SomeWindow -> WScreen -> TopEdge);
  3199.         }
  3200.  
  3201.         ScreenToFront(SomeWindow -> WScreen);
  3202.  
  3203.         ActivateWindow(SomeWindow);
  3204.     }
  3205. }
  3206.  
  3207.     /* PushWindow(struct Window *Window):
  3208.      *
  3209.      *    Push/PopWindow implement a single lifo window stack
  3210.      *    which always updates the window to activate when
  3211.      *    LSHIFT+RSHIFT+RETURN is pressed. This routine will
  3212.      *    push a window on the stack.
  3213.      */
  3214.  
  3215. VOID __regargs
  3216. PushWindow(struct Window *Window)
  3217. {
  3218.     if(WindowStackPtr < 5)
  3219.     {
  3220.         WindowStack[WindowStackPtr++] = Window;
  3221.  
  3222.         TopWindow = Window;
  3223.     }
  3224. }
  3225.  
  3226.     /* PopWindow():
  3227.      *
  3228.      *    Remove topmost window from window stack.
  3229.      */
  3230.  
  3231. VOID
  3232. PopWindow()
  3233. {
  3234.     if(WindowStackPtr > 0)
  3235.     {
  3236.         WindowStackPtr--;
  3237.  
  3238.         if(WindowStackPtr)
  3239.             TopWindow = WindowStack[WindowStackPtr - 1];
  3240.         else
  3241.             TopWindow = Window;
  3242.     }
  3243. }
  3244.  
  3245.     /* LoadMacros(STRPTR Name,struct MacroKeys *Keys):
  3246.      *
  3247.      *    Load the keyboard macros from a file.
  3248.      */
  3249.  
  3250. BYTE __regargs
  3251. LoadMacros(STRPTR Name,struct MacroKeys *Keys)
  3252. {
  3253.     struct IFFHandle    *Handle;
  3254.     BYTE             Success = FALSE;
  3255.     struct StoredProperty    *Prop;
  3256.     struct TermInfo        *TermInfo;
  3257.     LONG             Error;
  3258.  
  3259.     if(Handle = AllocIFF())
  3260.     {
  3261.         if(Handle -> iff_Stream = Open(Name,MODE_OLDFILE))
  3262.         {
  3263.             InitIFFasDOS(Handle);
  3264.  
  3265.             if(!(Error = OpenIFF(Handle,IFFF_READ)))
  3266.             {
  3267.                 /* Collect version number ID if
  3268.                  * available.
  3269.                  */
  3270.  
  3271.                 if(!(Error = PropChunks(Handle,(LONG *)VersionProps,1)))
  3272.                 {
  3273.                     /* The following line tells iffparse to stop at the
  3274.                      * very beginning of a `Type' chunk contained in a
  3275.                      * `TERM' FORM chunk.
  3276.                      */
  3277.  
  3278.                     if(!(Error = StopChunk(Handle,ID_TERM,ID_KEYS)))
  3279.                     {
  3280.                         /* Parse the file... */
  3281.  
  3282.                         if(!ParseIFF(Handle,IFFPARSE_SCAN))
  3283.                         {
  3284.                             /* Did we get a version ID? */
  3285.  
  3286.                             if(Prop = FindProp(Handle,ID_TERM,ID_VERS))
  3287.                             {
  3288.                                 TermInfo = (struct TermInfo *)Prop -> sp_Data;
  3289.  
  3290.                                 /* Is it the file format we are able
  3291.                                  * to read?
  3292.                                  */
  3293.  
  3294.                                 if((TermInfo -> Version > CONFIG_FILE_VERSION) || (TermInfo -> Version == CONFIG_FILE_VERSION && TermInfo -> Revision > CONFIG_FILE_REVISION) || (TermInfo -> Version == 1 && TermInfo -> Revision < 6))
  3295.                                 {
  3296.                                         /* Probably an older revision. */
  3297.  
  3298.                                     if(TermInfo -> Version == 1 && TermInfo -> Revision < 6)
  3299.                                     {
  3300.                                         memset(Keys,0,sizeof(struct MacroKeys));
  3301.  
  3302.                                         if(ReadChunkBytes(Handle,Keys,10 * 256) == 10 * 256)
  3303.                                             Success = TRUE;
  3304.                                         else
  3305.                                             Error = IoErr();
  3306.                                     }
  3307.                                     else
  3308.                                         Error = ERR_OUTDATED;
  3309.                                 }
  3310.                                 else
  3311.                                 {
  3312.                                     /* The file read pointer is positioned
  3313.                                      * just in front of the first data
  3314.                                      * to be read, so let's don't disappoint
  3315.                                      * iffparse and read it.
  3316.                                      */
  3317.  
  3318.                                     if(ReadChunkBytes(Handle,Keys,sizeof(struct MacroKeys)) == sizeof(struct MacroKeys))
  3319.                                         Success = TRUE;
  3320.                                     else
  3321.                                         Error = IoErr();
  3322.                                 }
  3323.                             }
  3324.                             else
  3325.                             {
  3326.                                     /* File was created by WriteIFFData previous
  3327.                                      * to revision 1.4.
  3328.                                      */
  3329.  
  3330.                                 memset(Keys,0,sizeof(struct MacroKeys));
  3331.  
  3332.                                 if(ReadChunkBytes(Handle,Keys,10 * 256) == 10 * 256)
  3333.                                     Success = TRUE;
  3334.                                 else
  3335.                                     Error = IoErr();
  3336.                             }
  3337.                         }
  3338.                     }
  3339.                 }
  3340.  
  3341.                 CloseIFF(Handle);
  3342.             }
  3343.  
  3344.             Close(Handle -> iff_Stream);
  3345.         }
  3346.         else
  3347.             Error = IoErr();
  3348.  
  3349.         FreeIFF(Handle);
  3350.     }
  3351.     else
  3352.         Error = ERR_NO_MEM;
  3353.  
  3354.     if(Error)
  3355.         SetIoErr(Error);
  3356.  
  3357.     return(Success);
  3358. }
  3359.  
  3360.     /* WriteIFFData(STRPTR Name,APTR Data,LONG Size,ULONG Type):
  3361.      *
  3362.      *    Write data to an IFF file (via iffparse.library).
  3363.      */
  3364.  
  3365. BYTE __regargs
  3366. WriteIFFData(STRPTR Name,APTR Data,LONG Size,ULONG Type)
  3367. {
  3368.     struct IFFHandle    *Handle;
  3369.     BYTE             Success = FALSE;
  3370.     LONG             Error;
  3371.  
  3372.         /* Allocate a handle. */
  3373.  
  3374.     if(Handle = AllocIFF())
  3375.     {
  3376.             /* Open an output stream. */
  3377.  
  3378.         if(Handle -> iff_Stream = Open(Name,MODE_NEWFILE))
  3379.         {
  3380.                 /* Tell iffparse that this is
  3381.                  * a DOS handle.
  3382.                  */
  3383.  
  3384.             InitIFFasDOS(Handle);
  3385.  
  3386.                 /* Open the handle for writing. */
  3387.  
  3388.             if(!(Error = OpenIFF(Handle,IFFF_WRITE)))
  3389.             {
  3390.                     /* Push outmost chunk onto stack. */
  3391.  
  3392.                 if(!(Error = PushChunk(Handle,ID_TERM,ID_FORM,IFFSIZE_UNKNOWN)))
  3393.                 {
  3394.                         /* Add a version identifier. */
  3395.  
  3396.                     if(!(Error = PushChunk(Handle,0,ID_VERS,IFFSIZE_UNKNOWN)))
  3397.                     {
  3398.                         struct TermInfo TermInfo;
  3399.  
  3400.                         TermInfo . Version    = CONFIG_FILE_VERSION;
  3401.                         TermInfo . Revision    = CONFIG_FILE_REVISION;
  3402.  
  3403.                             /* Write the version data. */
  3404.  
  3405.                         if(WriteChunkBytes(Handle,&TermInfo,sizeof(struct TermInfo)) == sizeof(struct TermInfo))
  3406.                         {
  3407.                                 /* Pop the version chunk, i.e. write it to the file. */
  3408.  
  3409.                             if(Error = PopChunk(Handle))
  3410.                                 Success = FALSE;
  3411.                             else
  3412.                             {
  3413.                                     /* Push the real data chunk on the stack. */
  3414.  
  3415.                                 if(!(Error = PushChunk(Handle,0,Type,IFFSIZE_UNKNOWN)))
  3416.                                 {
  3417.                                         /* Write the data. */
  3418.  
  3419.                                     if(WriteChunkBytes(Handle,Data,Size) == Size)
  3420.                                         Success = TRUE;
  3421.                                     else
  3422.                                         Error = IoErr();
  3423.  
  3424.                                             /* Pop the data chunk. */
  3425.  
  3426.                                     if(Success)
  3427.                                     {
  3428.                                         if(Error = PopChunk(Handle))
  3429.                                             Success = FALSE;
  3430.                                     }
  3431.                                 }
  3432.                                 else
  3433.                                     Success = FALSE;
  3434.                             }
  3435.                         }
  3436.                         else
  3437.                         {
  3438.                             Error = IoErr();
  3439.  
  3440.                             Success = FALSE;
  3441.                         }
  3442.                     }
  3443.  
  3444.                         /* Seems that we're done, now try to pop the FORM chunk
  3445.                          * and return.
  3446.                          */
  3447.  
  3448.                     if(Success)
  3449.                     {
  3450.                         if(Error = PopChunk(Handle))
  3451.                             Success = FALSE;
  3452.                     }
  3453.                 }
  3454.  
  3455.                     /* Close the handle (flush any pending data). */
  3456.  
  3457.                 CloseIFF(Handle);
  3458.             }
  3459.  
  3460.                 /* Close the DOS handle itself. */
  3461.  
  3462.             Close(Handle -> iff_Stream);
  3463.         }
  3464.         else
  3465.             Error = IoErr();
  3466.  
  3467.             /* And free the IFF handle. */
  3468.  
  3469.         FreeIFF(Handle);
  3470.     }
  3471.     else
  3472.         Error = ERR_NO_MEM;
  3473.  
  3474.     if(Success)
  3475.         AddProtection(Name,FIBF_EXECUTE);
  3476.  
  3477.     if(Error)
  3478.         SetIoErr(Error);
  3479.  
  3480.     return(Success);
  3481. }
  3482.  
  3483.     /* ReadIFFData(STRPTR Name,APTR Data,LONG Size,ULONG Type):
  3484.      *
  3485.      *    Read data from a `TERM' FORM chunk contained in an IFF file.
  3486.      */
  3487.  
  3488. BYTE __regargs
  3489. ReadIFFData(STRPTR Name,APTR Data,LONG Size,ULONG Type)
  3490. {
  3491.     struct IFFHandle    *Handle;
  3492.     BYTE             Success = FALSE;
  3493.     struct StoredProperty    *Prop;
  3494.     struct TermInfo        *TermInfo;
  3495.     LONG             Error = 0;
  3496.  
  3497.     if(Handle = AllocIFF())
  3498.     {
  3499.         if(Handle -> iff_Stream = Open(Name,MODE_OLDFILE))
  3500.         {
  3501.             InitIFFasDOS(Handle);
  3502.  
  3503.             if(!(Error = OpenIFF(Handle,IFFF_READ)))
  3504.             {
  3505.                 /* Collect version number ID if
  3506.                  * available.
  3507.                  */
  3508.  
  3509.                 if(!(Error = PropChunks(Handle,(LONG *)VersionProps,1)))
  3510.                 {
  3511.                     /* The following line tells iffparse to stop at the
  3512.                      * very beginning of a `Type' chunk contained in a
  3513.                      * `TERM' FORM chunk.
  3514.                      */
  3515.  
  3516.                     if(!(Error = StopChunk(Handle,ID_TERM,Type)))
  3517.                     {
  3518.                         /* Parse the file... */
  3519.  
  3520.                         if(!ParseIFF(Handle,IFFPARSE_SCAN))
  3521.                         {
  3522.                             /* Did we get a version ID? */
  3523.  
  3524.                             if(Prop = FindProp(Handle,ID_TERM,ID_VERS))
  3525.                             {
  3526.                                 TermInfo = (struct TermInfo *)Prop -> sp_Data;
  3527.  
  3528.                                 /* Is it the file format we are able
  3529.                                  * to read?
  3530.                                  */
  3531.  
  3532.                                 if((TermInfo -> Version > CONFIG_FILE_VERSION) || (TermInfo -> Version == CONFIG_FILE_VERSION && TermInfo -> Revision > CONFIG_FILE_REVISION) || (TermInfo -> Version == 1 && TermInfo -> Revision < 6))
  3533.                                 {
  3534.                                     Error = ERR_OUTDATED;
  3535.  
  3536.                                     Success = FALSE;
  3537.                                 }
  3538.                                 else
  3539.                                 {
  3540.                                     struct ContextNode *Chunk = CurrentChunk(Handle);
  3541.  
  3542.                                     if(Chunk -> cn_Size < Size)
  3543.                                         Size = Chunk -> cn_Size;
  3544.  
  3545.                                     /* The file read pointer is positioned
  3546.                                      * just in front of the first data
  3547.                                      * to be read, so let's don't disappoint
  3548.                                      * iffparse and read it.
  3549.                                      */
  3550.  
  3551.                                     if(ReadChunkBytes(Handle,Data,Size) == Size)
  3552.                                         Success = TRUE;
  3553.                                     else
  3554.                                         Error = IoErr();
  3555.                                 }
  3556.                             }
  3557.                         }
  3558.                     }
  3559.                 }
  3560.  
  3561.                 CloseIFF(Handle);
  3562.             }
  3563.  
  3564.             Close(Handle -> iff_Stream);
  3565.         }
  3566.         else
  3567.             Error = IoErr();
  3568.  
  3569.         FreeIFF(Handle);
  3570.     }
  3571.  
  3572.     if(Error)
  3573.         SetIoErr(Error);
  3574.  
  3575.     return(Success);
  3576. }
  3577.  
  3578.     /* SplitFileName():
  3579.      *
  3580.      *    Split a full file name into a file and a drawer name.
  3581.      */
  3582.  
  3583. VOID __regargs
  3584. SplitFileName(STRPTR FullName,STRPTR *FileName,STRPTR DrawerName)
  3585. {
  3586.     if(FilePart(FullName) == FullName)
  3587.     {
  3588.         *DrawerName    = 0;
  3589.         *FileName    = FullName;
  3590.     }
  3591.     else
  3592.     {
  3593.         STRPTR Dummy;
  3594.  
  3595.         strcpy(DrawerName,FullName);
  3596.  
  3597.         Dummy = PathPart(DrawerName);
  3598.  
  3599.         *Dummy = 0;
  3600.  
  3601.         *FileName = FilePart(FullName);
  3602.     }
  3603. }
  3604.  
  3605.     /* CreateList():
  3606.      *
  3607.      *    Create a small, empty list.
  3608.      */
  3609.  
  3610. struct List *
  3611. CreateList()
  3612. {
  3613.     struct List *List = (struct List *)AllocVecPooled(sizeof(struct MinList),MEMF_ANY);
  3614.  
  3615.     if(List)
  3616.         NewList(List);
  3617.  
  3618.     return(List);
  3619. }
  3620.  
  3621.     /* DeleteList():
  3622.      *
  3623.      *    Free the contents of a list and the list itself.
  3624.      */
  3625.  
  3626. VOID __regargs
  3627. DeleteList(struct List *List)
  3628. {
  3629.     if(List)
  3630.     {
  3631.         struct Node    *Node,
  3632.                 *Next;
  3633.  
  3634.         for(Node = List -> lh_Head ; Next = Node -> ln_Succ ; Node = Next)
  3635.             FreeVecPooled(Node);
  3636.  
  3637.         FreeVecPooled(List);
  3638.     }
  3639. }
  3640.  
  3641.     /* BackfillRoutine():
  3642.      *
  3643.      *    Window layer backfill routine.
  3644.      */
  3645.  
  3646. ULONG __asm __saveds
  3647. BackfillRoutine(register __a0 struct Hook *Hook,register __a1 struct {ULONG Layer; struct Rectangle Bounds;} *Bounds,register __a2 struct RastPort *RPort)
  3648. {
  3649.     struct RastPort RastPort = *RPort;
  3650.  
  3651.     RPort = &RastPort;
  3652.  
  3653.     RPort -> Layer = NULL;
  3654.  
  3655.     SetAPen(RPort,DrawInfo -> dri_Pens[BACKGROUNDPEN]);
  3656.     SetDrMd(RPort,JAM1);
  3657.  
  3658.     RectFill(RPort,Bounds -> Bounds . MinX,Bounds -> Bounds . MinY,Bounds -> Bounds . MaxX,Bounds -> Bounds . MaxY);
  3659.  
  3660.     return(TRUE);
  3661. }
  3662.  
  3663. struct NameSegment
  3664. {
  3665.     UBYTE    String[63],
  3666.         Separator;
  3667. };
  3668.  
  3669. STATIC UBYTE * __regargs
  3670. GetNameSegment(struct NameSegment *NameSegment,UBYTE *cp,WORD i)
  3671. {
  3672.     UBYTE *xp = NameSegment[i] . String;
  3673.  
  3674.     while (*cp && !strchr("._+-,@~=",*cp))
  3675.         *xp++ = *cp++;
  3676.  
  3677.     *xp = '\0';
  3678.  
  3679.     NameSegment[i] . Separator = *cp;
  3680.  
  3681.     if (*cp)
  3682.         cp++;
  3683.  
  3684.     if(NameSegment[i] . String[0] || NameSegment[i] . Separator)
  3685.         return(cp);
  3686.     else
  3687.         return(NULL);
  3688. }
  3689.  
  3690. STATIC VOID __regargs
  3691. CopyNameSegment(struct NameSegment *NameSegment,UBYTE *Destination,WORD Zap)
  3692. {
  3693.     UBYTE *cp = Destination,*xp;
  3694.  
  3695.     for(xp = NameSegment[0] . String ; *xp ; )
  3696.         *cp++ = *xp++;
  3697.  
  3698.     if(NameSegment[0] . Separator)
  3699.     {
  3700.         register WORD i;
  3701.  
  3702.         *cp++ = NameSegment[0] . Separator;
  3703.  
  3704.         for(i = Zap + 1 ; ; i++)
  3705.         {
  3706.             for(xp = NameSegment[i] . String ; *xp ; )
  3707.                 *cp++ = *xp++;
  3708.  
  3709.             if(NameSegment[i] . Separator)
  3710.                 *cp++ = NameSegment[i] . Separator;
  3711.             else
  3712.             {
  3713.                 if(!NameSegment[i] . String[0])
  3714.                     break;
  3715.             }
  3716.         }
  3717.     }
  3718.  
  3719.     *cp = 0;
  3720. }
  3721.  
  3722.     /* ShrinkName():
  3723.      *
  3724.      *    Shrink a file name down to a number of characters, if
  3725.      *    possible preserving the structure of the name. Algorithm
  3726.      *    courtesy of the "shrink" program by Simon Brown,
  3727.      *    Edinburgh University.
  3728.      */
  3729.  
  3730. UBYTE * __regargs
  3731. ShrinkName(const UBYTE *Source,UBYTE *Destination,WORD MaxLength,BOOLEAN FixSuffix)
  3732. {
  3733.     #define MAXSEGS 10
  3734.  
  3735.     struct NameSegment NameSegment[MAXSEGS];
  3736.  
  3737.     WORD i,NumSegments,SuffixLength,Remainder,Delete,Total,Zap = 0;
  3738.     UBYTE *OldPtr = (UBYTE *)Source;
  3739.  
  3740.     for(i = 0 ; i < MAXSEGS && (OldPtr = GetNameSegment(NameSegment,OldPtr,i)) ; i++);
  3741.  
  3742.     if(i < MAXSEGS)
  3743.     {
  3744.         NumSegments = i - 1;
  3745.  
  3746.         if((NumSegments * 2) < MaxLength)
  3747.         {
  3748.             SuffixLength = strlen(NameSegment[NumSegments] . String);
  3749.  
  3750.             if(SuffixLength > MaxLength - NumSegments - 1)
  3751.             {
  3752.                 SuffixLength = MaxLength - (2 * NumSegments) - 1;
  3753.  
  3754.                 NameSegment[NumSegments] . String[SuffixLength - 1] = 0;
  3755.             }
  3756.             else
  3757.             {
  3758.                 if (SuffixLength + NumSegments > MaxLength-NumSegments-1)
  3759.                     Zap = NumSegments - (MaxLength-SuffixLength)/2;
  3760.             }
  3761.  
  3762.             if(NumSegments >= 1)
  3763.             {
  3764.                 for(i = Zap + 1 ; i <= NumSegments ; i++)
  3765.                 {
  3766.                     if(NameSegment[i] . Separator)
  3767.                         SuffixLength++;
  3768.                 }
  3769.  
  3770.                 if(NameSegment[0] . Separator)
  3771.                     SuffixLength++;
  3772.  
  3773.                 Remainder = MaxLength - SuffixLength;
  3774.  
  3775.                 Delete = Remainder / NumSegments;
  3776.  
  3777.                 Total = SuffixLength;
  3778.  
  3779.                 for(i = Zap + 1 ; i < NumSegments ; i++)
  3780.                 {
  3781.                     NameSegment[i] . String[Delete] = 0;
  3782.  
  3783.                     Total += Delete;
  3784.                 }
  3785.  
  3786.                 NameSegment[0] . String[MaxLength - Total] = 0;
  3787.             }
  3788.  
  3789.             CopyNameSegment(NameSegment,Destination,Zap);
  3790.         }
  3791.         else
  3792.             strcpy(Destination,Source);
  3793.     }
  3794.     else
  3795.         strcpy(Destination,Source);
  3796.  
  3797.     if(FixSuffix)
  3798.     {
  3799.         BOOLEAN    GotDot    = FALSE;
  3800.         LONG    Len    = strlen(Destination),Dots;
  3801.  
  3802.         for(i = Dots = 0 ; i < Len ; i++)
  3803.         {
  3804.             if(Destination[i] == '.')
  3805.                 Dots++;
  3806.         }
  3807.  
  3808.         if(!Dots)
  3809.         {
  3810.             if(Len < 4)
  3811.                 strcat(Destination,".___");
  3812.             else
  3813.                 Destination[Len - 4] = '.';
  3814.         }
  3815.  
  3816.         for(i = Len - 1 ; i >= 0 ; i--)
  3817.         {
  3818.             if(Destination[i] == '.')
  3819.             {
  3820.                 if(GotDot)
  3821.                     Destination[i] = '_';
  3822.                 else
  3823.                     GotDot = TRUE;
  3824.             }
  3825.  
  3826.             if(Destination[i] == '\\')
  3827.                 Destination[i] = '-';
  3828.         }
  3829.     }
  3830.  
  3831.     return(Destination);
  3832. }
  3833.  
  3834.     /* BuildFontName(STRPTR Destination,const STRPTR Name,LONG Size):
  3835.      *
  3836.      *    Build a font name and size string from given
  3837.      *    information (raw name and size).
  3838.      */
  3839.  
  3840. VOID __regargs
  3841. BuildFontName(STRPTR Destination,const STRPTR Name,LONG Size)
  3842. {
  3843.     UBYTE    LocalBuffer[50];
  3844.     LONG    Len;
  3845.  
  3846.     strcpy(LocalBuffer,FilePart((STRPTR)Name));
  3847.  
  3848.     Len = strlen(LocalBuffer);
  3849.  
  3850.     if(Len > 5)
  3851.     {
  3852.         if(!Stricmp(&LocalBuffer[Len - 5],".font"))
  3853.             LocalBuffer[Len - 5] = 0;
  3854.     }
  3855.  
  3856.     SPrintf(Destination,"%s %ld",LocalBuffer,Size);
  3857. }
  3858.  
  3859.     /* CreateMenuGlyphs():
  3860.      *
  3861.      *    Create scaled glyphs for pull-down menus.
  3862.      */
  3863.  
  3864. BOOLEAN __regargs
  3865. CreateMenuGlyphs(struct Screen *Screen,struct DrawInfo *DrawInfo,struct Image **AmigaPtr,struct Image **CheckPtr)
  3866. {
  3867.     struct Image    *AmigaGlyph,
  3868.             *CheckGlyph;
  3869.     LONG         AspectX,AspectY,
  3870.              Size,FontHeight;
  3871.  
  3872.     FontHeight = DrawInfo -> dri_Font -> tf_Baseline + 2;
  3873.  
  3874.     if(Screen -> Flags & SCREENHIRES)
  3875.         Size = SYSISIZE_MEDRES;
  3876.     else
  3877.         Size = SYSISIZE_LOWRES;
  3878.  
  3879.     AspectX = DrawInfo -> dri_Resolution . X;
  3880.     AspectY = DrawInfo -> dri_Resolution . Y;
  3881.  
  3882.     if(AmigaGlyph = NewObject(NULL,SYSICLASS,
  3883.         SYSIA_DrawInfo,    DrawInfo,
  3884.         SYSIA_Size,    Size,
  3885.         SYSIA_Which,    AMIGAKEY,
  3886.         IA_Left,    0,
  3887.         LA_Top,        0,
  3888.         IA_Width,    (FontHeight * 3 * AspectY) / (2 * AspectX),
  3889.         IA_Height,    FontHeight,
  3890.     TAG_DONE))
  3891.     {
  3892.         if(!(CheckGlyph = NewObject(NULL,SYSICLASS,
  3893.             SYSIA_DrawInfo,    DrawInfo,
  3894.             SYSIA_Size,    Size,
  3895.             SYSIA_Which,    MENUCHECK,
  3896.             IA_Left,    0,
  3897.             LA_Top,        0,
  3898.             IA_Width,    (FontHeight * AspectY) / AspectX,
  3899.             IA_Height,    FontHeight,
  3900.         TAG_DONE)))
  3901.         {
  3902.             DisposeObject(AmigaGlyph);
  3903.  
  3904.             AmigaGlyph = NULL;
  3905.         }
  3906.     }
  3907.  
  3908.     if(AmigaGlyph && CheckGlyph)
  3909.     {
  3910.         *AmigaPtr = AmigaGlyph;
  3911.         *CheckPtr = CheckGlyph;
  3912.  
  3913.         return(TRUE);
  3914.     }
  3915.     else
  3916.         return(FALSE);
  3917. }
  3918.  
  3919.     /* FixName(STRPTR Name):
  3920.      *
  3921.      *    Build a correct AmigaDOS filename.
  3922.      */
  3923.  
  3924. VOID __regargs
  3925. FixName(STRPTR Name)
  3926. {
  3927.     WORD    NameLen    = strlen(Name),
  3928.         i;
  3929.  
  3930.         /* Replace special characters. */
  3931.  
  3932.     for(i = 0 ; i < NameLen ; i++)
  3933.     {
  3934.         switch(Name[i])
  3935.         {
  3936.             case ' ':
  3937.  
  3938.                 Name[i] = '_';
  3939.                 break;
  3940.  
  3941.             case ':':
  3942.  
  3943.                 Name[i] = '.';
  3944.                 break;
  3945.  
  3946.             case '/':
  3947.  
  3948.                 Name[i] = '\\';
  3949.                 break;
  3950.  
  3951.             case '\"':
  3952.  
  3953.                 Name[i] = '\'';
  3954.                 break;
  3955.         }
  3956.     }
  3957.  
  3958.         /* Truncate the name. */
  3959.  
  3960.     if(NameLen > 31)
  3961.         Name[31] = 0;
  3962. }
  3963.  
  3964.     /* ShowError(struct Window *Window,LONG Primary,LONG Secondary,STRPTR String):
  3965.      *
  3966.      *    Display an error message, in human readable form if possible.
  3967.      */
  3968.  
  3969. VOID __regargs
  3970. ShowError(struct Window *Window,LONG Primary,LONG Secondary,STRPTR String)
  3971. {
  3972.     STATIC LONG LocalErrors[][2] =
  3973.     {
  3974.         ERR_SAVE_ERROR,            MSG_ERR_COULD_NOT_SAVE_FILE_TXT,
  3975.         ERR_LOAD_ERROR,            MSG_ERR_COULD_NOT_LOAD_FILE_TXT,
  3976.         ERR_NO_MEM,            MSG_ERR_NO_MEM_TXT,
  3977.         ERR_OUTDATED,            MSG_ERR_OUTDATED_TXT,
  3978.         ERR_EXECUTE_ERROR,        MSG_ERR_COULD_NOT_EXECUTE_PROGRAM_TXT,
  3979.  
  3980.         ERR_FILE_NOT_FOUND,        MSG_VERIFY_NO_FILE_TXT,
  3981.         ERR_DRAWER_NOT_FOUND,        MSG_VERIFY_DRAWER_NOT_FOUND_TXT,
  3982.         ERR_PROGRAM_NOT_FOUND,        MSG_VERIFY_NO_PROGRAM_TXT,
  3983.         ERR_NOT_A_FILE,            MSG_VERIFY_DRAWER_NOT_A_FILE_TXT,
  3984.         ERR_NOT_A_DRAWER,        MSG_VERIFY_FILE_NOT_A_DRAWER_TXT,
  3985.  
  3986.         IFFERR_NOMEM,            MSG_IFFERR_NOMEM_TXT,
  3987.         IFFERR_READ,            MSG_IFFERR_READ_TXT,
  3988.         IFFERR_WRITE,            MSG_IFFERR_WRITE_TXT,
  3989.         IFFERR_SEEK,            MSG_IFFERR_SEEK_TXT,
  3990.         IFFERR_MANGLED,            MSG_IFFERR_MANGLED_TXT,
  3991.         IFFERR_NOTIFF,            MSG_IFFERR_NOTIFF_TXT,
  3992.  
  3993.         0,                0
  3994.     };
  3995.  
  3996.     STRPTR    PrimaryError    = NULL,
  3997.         SecondaryError    = NULL;
  3998.  
  3999.     if(Primary)
  4000.     {
  4001.         LONG i;
  4002.  
  4003.         for(i = 0 ; LocalErrors[i][0] ; i++)
  4004.         {
  4005.             if(LocalErrors[i][0] == Primary)
  4006.             {
  4007.                 PrimaryError = LocaleString(LocalErrors[i][1]);
  4008.  
  4009.                 break;
  4010.             }
  4011.         }
  4012.  
  4013.         if(!PrimaryError)
  4014.         {
  4015.             STATIC UBYTE __far Buffer[256];
  4016.  
  4017.             Fault(Primary,"",Buffer,256);
  4018.  
  4019.             PrimaryError = Buffer + 2;
  4020.         }
  4021.     }
  4022.  
  4023.     if(Secondary)
  4024.     {
  4025.         LONG i;
  4026.  
  4027.         for(i = 0 ; LocalErrors[i][0] ; i++)
  4028.         {
  4029.             if(LocalErrors[i][0] == Secondary)
  4030.             {
  4031.                 SecondaryError = LocaleString(LocalErrors[i][1]);
  4032.  
  4033.                 break;
  4034.             }
  4035.         }
  4036.  
  4037.         if(!SecondaryError)
  4038.         {
  4039.             STATIC UBYTE __far Buffer[256];
  4040.  
  4041.             Fault(Secondary,"",Buffer,256);
  4042.  
  4043.             SecondaryError = Buffer + 2;
  4044.         }
  4045.     }
  4046.  
  4047.     if(PrimaryError)
  4048.     {
  4049.         if(String)
  4050.             MyEasyRequest(Window,PrimaryError,LocaleString(MSG_GLOBAL_CONTINUE_TXT),String,SecondaryError);
  4051.         else
  4052.             MyEasyRequest(Window,PrimaryError,LocaleString(MSG_GLOBAL_CONTINUE_TXT),SecondaryError);
  4053.     }
  4054. }
  4055.  
  4056. struct RendezvousData * __saveds __asm
  4057. RendezvousLogin(register __a0 struct MsgPort *ReadPort,register __a1 struct MsgPort *WritePort,register __a2 struct TagItem *TagList)
  4058. {
  4059.     struct RendezvousData *Data;
  4060.  
  4061.     if(Data = (struct RendezvousData *)AllocVecPooled(sizeof(struct RendezvousData),MEMF_ANY | MEMF_CLEAR))
  4062.     {
  4063.         struct DataMsg Msg;
  4064.  
  4065.         InitMsgItem(&Msg,TaskDestructor);
  4066.  
  4067.         Msg . Type = DATAMSGTYPE_RENDEZVOUS;
  4068.         Msg . Data = (UBYTE *)SysBase -> ThisTask;
  4069.  
  4070.         Forbid();
  4071.  
  4072.         ClrSignal(SIGBREAKF_CTRL_F);
  4073.  
  4074.         PutMsgItem(SpecialQueue,(struct MsgItem *)&Msg);
  4075.  
  4076.         Wait(SIGBREAKF_CTRL_F);
  4077.  
  4078.         Permit();
  4079.  
  4080.         if(ReadRequest && WriteRequest)
  4081.         {
  4082.             struct List *UploadList;
  4083.  
  4084.             CopyMem(ReadRequest,&Data -> rd_ReadRequest,sizeof(struct IOExtSer));
  4085.  
  4086.             Data -> rd_ReadRequest . IOSer . io_Message . mn_ReplyPort = ReadPort;
  4087.  
  4088.             CopyMem(WriteRequest,&Data -> rd_WriteRequest,sizeof(struct IOExtSer));
  4089.  
  4090.             Data -> rd_WriteRequest . IOSer . io_Message . mn_ReplyPort = WritePort;
  4091.  
  4092.             if(Window)
  4093.                 Data -> rd_Screen = Window -> WScreen;
  4094.  
  4095.             NewList(&Data -> rd_UploadList);
  4096.             NewList(&Data -> rd_DownloadList);
  4097.             NewList(&Data -> rd_SentList);
  4098.             NewList(&Data -> rd_ReceivedList);
  4099.  
  4100.             if(UploadList = GetUploadList())
  4101.             {
  4102.                 struct Node *Node,*Next;
  4103.  
  4104.                 for(Node = UploadList -> lh_Head ; Next = Node -> ln_Succ ; Node = Next)
  4105.                     AddTail(&Data -> rd_UploadList,Node);
  4106.  
  4107.                 FreeVecPooled(UploadList);
  4108.             }
  4109.  
  4110.             Data -> rd_SendPath    = Config -> PathConfig -> BinaryUploadPath;
  4111.             Data -> rd_ReceivePath    = Config -> PathConfig -> BinaryDownloadPath;
  4112.             Data -> rd_Options    = "";
  4113.         }
  4114.         else
  4115.         {
  4116.             FreeVecPooled(Data);
  4117.  
  4118.             Data = NULL;
  4119.         }
  4120.     }
  4121.  
  4122.     return(Data);
  4123. }
  4124.  
  4125. VOID __saveds __asm
  4126. RendezvousLogoff(register __a0 struct RendezvousData *Data)
  4127. {
  4128.     if(Data)
  4129.     {
  4130.         struct Node *Node,*Next;
  4131.  
  4132.         for(Node = Data -> rd_UploadList . lh_Head ; Next = Node -> ln_Succ ; Node = Next)
  4133.             FreeVecPooled(Node);
  4134.  
  4135.         for(Node = Data -> rd_DownloadList . lh_Head ; Next = Node -> ln_Succ ; Node = Next)
  4136.             FreeVecPooled(Node);
  4137.  
  4138.         for(Node = Data -> rd_SentList . lh_Head ; Next = Node -> ln_Succ ; Node = Next)
  4139.             FreeVecPooled(Node);
  4140.  
  4141.         for(Node = Data -> rd_ReceivedList . lh_Head ; Next = Node -> ln_Succ ; Node = Next)
  4142.             FreeVecPooled(Node);
  4143.  
  4144.         FreeVecPooled(Data);
  4145.  
  4146.         Signal(ThisProcess,SIG_HANDSHAKE);
  4147.     }
  4148. }
  4149.  
  4150. struct Node * __saveds __asm
  4151. RendezvousNewNode(register __a0 STRPTR Name)
  4152. {
  4153.     if(Name)
  4154.     {
  4155.         LONG Len;
  4156.  
  4157.         if(Len = strlen(Name))
  4158.         {
  4159.             struct Node *Node;
  4160.  
  4161.             if(Node = (struct Node *)AllocVecPooled(sizeof(struct Node) + Len + 1,MEMF_ANY))
  4162.             {
  4163.                 memset(Node,0,sizeof(struct Node));
  4164.  
  4165.                 strcpy(Node -> ln_Name = (STRPTR)(Node + 1),Name);
  4166.  
  4167.                 return(Node);
  4168.             }
  4169.         }
  4170.     }
  4171.  
  4172.     return(NULL);
  4173. }
  4174.  
  4175. struct List * __regargs
  4176. BuildModeList(LONG *Index,ULONG DisplayMode,ULONG (* __asm ModeFilter)(register __a1 ULONG ID))
  4177. {
  4178.     struct List    *List;
  4179.     LONG         Count = 0;
  4180.  
  4181.     *Index = 0;
  4182.  
  4183.     if(List = (struct List *)AllocVecPooled(sizeof(struct List),MEMF_ANY))
  4184.     {
  4185.         struct DisplayInfo    DisplayInfo;
  4186.         ULONG            SomeMode = INVALID_ID;
  4187.  
  4188.         NewList(List);
  4189.  
  4190.         while((SomeMode = NextDisplayInfo(SomeMode)) != INVALID_ID)
  4191.         {
  4192.             if(GetDisplayInfoData(NULL,(APTR)&DisplayInfo,sizeof(struct DisplayInfo),DTAG_DISP,SomeMode))
  4193.             {
  4194.                 if((DisplayInfo . PropertyFlags & DIPF_IS_WB) && !DisplayInfo . NotAvailable)
  4195.                 {
  4196.                     STRPTR Name;
  4197.  
  4198.                     if(ModeFilter)
  4199.                     {
  4200.                         if(!(*ModeFilter)(SomeMode))
  4201.                             continue;
  4202.                     }
  4203.  
  4204.                     if(Name = GetModeName(SomeMode))
  4205.                     {
  4206.                         struct ModeNode    *ModeNode;
  4207.  
  4208.                         if(ModeNode = (struct ModeNode *)AllocVecPooled(sizeof(struct ModeNode) + strlen(Name) + 1,MEMF_ANY))
  4209.                         {
  4210.                             ModeNode -> VanillaNode . ln_Name = (STRPTR)(ModeNode + 1);
  4211.  
  4212.                             strcpy(ModeNode -> VanillaNode . ln_Name,Name);
  4213.  
  4214.                             ModeNode -> DisplayID = SomeMode;
  4215.  
  4216.                             AddTail(List,ModeNode);
  4217.  
  4218.                             Count++;
  4219.                         }
  4220.                     }
  4221.                 }
  4222.             }
  4223.         }
  4224.     }
  4225.  
  4226.     if(Count)
  4227.     {
  4228.         struct ModeNode    *Node,
  4229.                 *Next;
  4230.  
  4231.         for(Node = (struct ModeNode *)List -> lh_Head ; Node -> VanillaNode . ln_Succ ; Node = (struct ModeNode *)Node -> VanillaNode . ln_Succ)
  4232.         {
  4233.             if(!(Node -> DisplayID & MONITOR_ID_MASK))
  4234.             {
  4235.                 for(Next = (struct ModeNode *)List -> lh_Head ; Next -> VanillaNode . ln_Succ ; Next = (struct ModeNode *)Next -> VanillaNode . ln_Succ)
  4236.                 {
  4237.                     if((Node -> DisplayID & ~MONITOR_ID_MASK) == (Next -> DisplayID & ~MONITOR_ID_MASK) && Next != Node)
  4238.                         Node -> DisplayID = INVALID_ID;
  4239.                 }
  4240.             }
  4241.  
  4242.             for(Next = (struct ModeNode *)List -> lh_Head ; Next -> VanillaNode . ln_Succ ; Next = (struct ModeNode *)Next -> VanillaNode . ln_Succ)
  4243.             {
  4244.                 if(Node -> DisplayID == Next -> DisplayID && Next != Node)
  4245.                     Next -> DisplayID = INVALID_ID;
  4246.             }
  4247.         }
  4248.  
  4249.         for(Node = (struct ModeNode *)List -> lh_Head ; Next = (struct ModeNode *)Node -> VanillaNode . ln_Succ ; Node = Next)
  4250.         {
  4251.             if(Node -> DisplayID == INVALID_ID)
  4252.             {
  4253.                 Count--;
  4254.  
  4255.                 Remove(Node);
  4256.  
  4257.                 FreeVecPooled(Node);
  4258.             }
  4259.         }
  4260.     }
  4261.  
  4262.     if(Count)
  4263.     {
  4264.         struct ModeNode    *Node,
  4265.                 *Next;
  4266.  
  4267.         for(Count = 0, Node = (struct ModeNode *)List -> lh_Head ; Next = (struct ModeNode *)Node -> VanillaNode . ln_Succ ; Node = Next)
  4268.         {
  4269.             if(Node -> DisplayID == DisplayMode)
  4270.             {
  4271.                 *Index = Count;
  4272.  
  4273.                 break;
  4274.             }
  4275.         }
  4276.  
  4277.         return(List);
  4278.     }
  4279.     else
  4280.     {
  4281.         DeleteList(List);
  4282.  
  4283.         return(NULL);
  4284.     }
  4285. }
  4286.  
  4287.     /* IsAssign(STRPTR Name):
  4288.      *
  4289.      *    Does a name refer to an assignment?
  4290.      */
  4291.  
  4292. BOOLEAN __regargs
  4293. IsAssign(STRPTR Name)
  4294. {
  4295.     WORD NameLen    = strlen(Name) - 1;
  4296.     BOOLEAN Result    = FALSE;
  4297.  
  4298.         /* Does it end with a colon? */
  4299.  
  4300.     if(Name[NameLen] == ':')
  4301.     {
  4302.         struct DosList *DosList;
  4303.  
  4304.             /* Lock the list of assignments for reading. */
  4305.  
  4306.         DosList = AttemptLockDosList(LDF_ASSIGNS | LDF_READ);
  4307.  
  4308.             /* Make sure the v37 bug doesn't catch us. */
  4309.  
  4310.         if(((ULONG)DosList) > 1)
  4311.         {
  4312.             STRPTR AssignName;
  4313.  
  4314.                 /* Scan the list... */
  4315.  
  4316.             while(DosList = NextDosEntry(DosList,LDF_ASSIGNS))
  4317.             {
  4318.                     /* Convert the name from icky
  4319.                      * BCPL to `C' style string.
  4320.                      */
  4321.  
  4322.                 AssignName = (STRPTR)BADDR(DosList -> dol_Name);
  4323.  
  4324.                     /* Does the name length match? */
  4325.  
  4326.                 if(AssignName[0] == NameLen)
  4327.                 {
  4328.                         /* Does the name itself match? */
  4329.  
  4330.                     if(!Strnicmp(&AssignName[1],Name,NameLen))
  4331.                     {
  4332.                         Result = TRUE;
  4333.  
  4334.                         break;
  4335.                     }
  4336.                 }
  4337.             }
  4338.  
  4339.                 /* Unlock the list of assignments. */
  4340.  
  4341.             UnLockDosList(LDF_ASSIGNS | LDF_READ);
  4342.         }
  4343.     }
  4344.  
  4345.         /* Return the result. */
  4346.  
  4347.     return(Result);
  4348. }
  4349.  
  4350.     /* LockInAssign(BPTR TheLock,STRPTR TheAssignment):
  4351.      *
  4352.      *    Check if a file lock is part of an assignment.
  4353.      */
  4354.  
  4355. BOOLEAN __regargs
  4356. LockInAssign(BPTR TheLock,STRPTR TheAssignment)
  4357. {
  4358.     struct DevProc    *DevProc    = NULL;
  4359.     struct MsgPort    *FileSysTask    = GetFileSysTask();
  4360.     BOOLEAN         Result        = FALSE;
  4361.  
  4362.  
  4363.         /* Loop until all assignments are
  4364.          * processed.
  4365.          */
  4366.  
  4367.     do
  4368.     {
  4369.             /* Get the default filesystem task
  4370.              * in case we stumble upon NULL
  4371.              * directory locks.
  4372.              */
  4373.  
  4374.         if(DevProc = GetDeviceProc(TheAssignment,DevProc))
  4375.         {
  4376.                 /* Set the default filesystem task. */
  4377.  
  4378.             SetFileSysTask(DevProc -> dvp_Port);
  4379.  
  4380.                 /* Is the lock on the list? */
  4381.  
  4382.             if(SameLock(DevProc -> dvp_Lock,TheLock) == LOCK_SAME)
  4383.                 Result = TRUE;
  4384.         }
  4385.         else
  4386.             break;
  4387.     }
  4388.     while(DevProc && (DevProc -> dvp_Flags & DVPF_ASSIGN) && !Result);
  4389.  
  4390.         /* Reset the default filesystem task. */
  4391.  
  4392.     SetFileSysTask(FileSysTask);
  4393.  
  4394.         /* Free device process data. */
  4395.  
  4396.     if(DevProc)
  4397.         FreeDeviceProc(DevProc);
  4398.  
  4399.     return(Result);
  4400. }
  4401.  
  4402.     /* DeleteBitMap(struct BitMap *BitMap):
  4403.      *
  4404.      *    Delete a bitmap created by CreateBitMap().
  4405.      */
  4406.  
  4407. VOID __regargs
  4408. DeleteBitMap(struct BitMap *BitMap)
  4409. {
  4410.     WaitBlit();
  4411.  
  4412.     if(Kick30)
  4413.         FreeBitMap(BitMap);
  4414.     else
  4415.     {
  4416.         LONG i;
  4417.  
  4418.         for(i = 0 ; i < BitMap -> Depth ; i++)
  4419.         {
  4420.             if(BitMap -> Planes[i])
  4421.                 FreeVec(BitMap -> Planes[i]);
  4422.         }
  4423.  
  4424.         FreeVecPooled(BitMap);
  4425.     }
  4426. }
  4427.  
  4428.     /* CreateBitMap(ULONG Width,ULONG Height,ULONG Depth,ULONG Flags,struct BitMap *Friend):
  4429.      *
  4430.      *    Create a new bitmap with given properties.
  4431.      */
  4432.  
  4433. struct BitMap * __regargs
  4434. CreateBitMap(ULONG Width,ULONG Height,ULONG Depth,ULONG Flags,struct BitMap *Friend)
  4435. {
  4436.     if(Kick30)
  4437.         return(AllocBitMap(Width,Height,Depth,Flags,Friend));
  4438.     else
  4439.     {
  4440.         struct BitMap    *BitMap;
  4441.         LONG         Plus;
  4442.  
  4443.         if(Depth > 8)
  4444.             Plus = (Depth - 8) * sizeof(PLANEPTR);
  4445.         else
  4446.             Plus = 0;
  4447.  
  4448.         if(BitMap = (struct BitMap *)AllocVecPooled(sizeof(struct BitMap) + Plus,MEMF_CLEAR))
  4449.         {
  4450.             LONG i,PageSize;
  4451.  
  4452.             InitBitMap(BitMap,Depth,Width,Height);
  4453.  
  4454.             PageSize = BitMap -> BytesPerRow * BitMap -> Rows;
  4455.  
  4456.             for(i = 0 ; i < BitMap -> Depth ; i++)
  4457.             {
  4458.                 if(!(BitMap -> Planes[i] = (PLANEPTR)AllocVec(PageSize,MEMF_CHIP)))
  4459.                 {
  4460.                     LONG j;
  4461.  
  4462.                     for(j = 0 ; j < i ; j++)
  4463.                         FreeVec(BitMap -> Planes[j]);
  4464.  
  4465.                     FreeVecPooled(BitMap);
  4466.  
  4467.                     return(NULL);
  4468.                 }
  4469.             }
  4470.  
  4471.             if(Flags & BMF_CLEAR)
  4472.                 BltBitMap(BitMap,0,0,BitMap,0,0,Width,Height,0x00,(1 << Depth) - 1,NULL);
  4473.         }
  4474.  
  4475.         return(BitMap);
  4476.     }
  4477. }
  4478.  
  4479.     /* LaunchCommand(STRPTR Command):
  4480.      *
  4481.      *    Launch a command, try to figure out if it's an ARexx
  4482.      *    command, a plain batch file or a program and act
  4483.      *    accordingly.
  4484.      */
  4485.  
  4486. LONG __regargs
  4487. LaunchCommand(STRPTR Command)
  4488. {
  4489.     UBYTE    LocalBuffer[MAX_FILENAME_LENGTH];
  4490.     BPTR    Stream,
  4491.         OutputStream;
  4492.     APTR    OldConsoleTask    = ThisProcess -> pr_ConsoleTask;
  4493.     BOOL    IsScript    = FALSE,
  4494.         IsRexx        = FALSE;
  4495.     LONG    Result;
  4496.     BPTR    CommandFile;
  4497.     UBYTE    NameBuffer[MAX_FILENAME_LENGTH];
  4498.     BPTR    FileLock;
  4499.     STRPTR    OtherName;
  4500.     WORD    i;
  4501.  
  4502.         /* Chop off the arguments. */
  4503.  
  4504.     memcpy(NameBuffer,Command,MAX_FILENAME_LENGTH - 1);
  4505.  
  4506.     NameBuffer[MAX_FILENAME_LENGTH - 1] = 0;
  4507.  
  4508.     for(i = 0 ; i < MAX_FILENAME_LENGTH ; i++)
  4509.     {
  4510.         if(NameBuffer[i] == ' ')
  4511.         {
  4512.             NameBuffer[i] = 0;
  4513.             break;
  4514.         }
  4515.     }
  4516.  
  4517.         /* Now do something useful. Check if the command
  4518.          * could be an ARexx script.
  4519.          */
  4520.  
  4521.     if(CommandFile = Open(NameBuffer,MODE_OLDFILE))
  4522.     {
  4523.         LONG Len;
  4524.  
  4525.             /* 256 bytes may be not be enough, but then
  4526.              * we're only guessing.
  4527.              */
  4528.  
  4529.         if((Len = Read(CommandFile,LocalBuffer,MAX_FILENAME_LENGTH)) > 0)
  4530.         {
  4531.             register UBYTE    c;
  4532.             LONG        i;
  4533.  
  4534.             for(i = 0 ; i < Len - 1 ; i++)
  4535.             {
  4536.                 c = LocalBuffer[i];
  4537.  
  4538.                     /* Stop on invalid characters. */
  4539.  
  4540.                 if((c < ' ' && c != '\r' && c != '\n' && c != '\a') || (c >= 127 && c < 160))
  4541.                     break;
  4542.                 else
  4543.                 {
  4544.                         /* Looks like the typical
  4545.                          * introductory comment line.
  4546.                          */
  4547.  
  4548.                     if(c == '/' && LocalBuffer[i + 1] == '*')
  4549.                     {
  4550.                         IsRexx = TRUE;
  4551.                         break;
  4552.                     }
  4553.                 }
  4554.             }
  4555.         }
  4556.  
  4557.         Close(CommandFile);
  4558.     }
  4559.  
  4560.         /* Ok, second check. Does it have the script bit set? */
  4561.  
  4562.     if(FileLock = Lock(NameBuffer,ACCESS_READ))
  4563.     {
  4564.         struct FileInfoBlock __aligned FileInfo;
  4565.  
  4566.         if(Examine(FileLock,&FileInfo))
  4567.         {
  4568.             if(FileInfo . fib_Protection & FIBF_SCRIPT)
  4569.                 IsScript = TRUE;
  4570.         }
  4571.  
  4572.         UnLock(FileLock);
  4573.     }
  4574.  
  4575.         /* If it's an ARexx command, launch it. */
  4576.  
  4577.     if(IsRexx)
  4578.     {
  4579.         SendARexxCommand(Command,TRUE);
  4580.  
  4581.         return(0);
  4582.     }
  4583.  
  4584.         /* If it's a script command, prepend the "Execute "
  4585.          * command. It's not perfect but it should work.
  4586.          */
  4587.  
  4588.     if(IsScript)
  4589.     {
  4590.         if(OtherName = AllocVecPooled(strlen("Execute ") + strlen(Command) + 1,MEMF_ANY))
  4591.         {
  4592.             strcpy(OtherName,"Execute ");
  4593.             strcat(OtherName,Command);
  4594.  
  4595.             Command = OtherName;
  4596.         }
  4597.     }
  4598.     else
  4599.         OtherName = NULL;
  4600.  
  4601.     if(WindowName[0])
  4602.     {
  4603.         UBYTE LocalName[MAXPUBSCREENNAME + 1];
  4604.  
  4605.         if(Window)
  4606.         {
  4607.             if(!GetPubScreenName(Window -> WScreen,LocalName))
  4608.                 LocalName[0] = 0;
  4609.         }
  4610.  
  4611.         if(LocalName[0])
  4612.         {
  4613.             SPrintf(LocalBuffer,WindowName,LocalName);
  4614.  
  4615.             Stream = Open(LocalBuffer,MODE_NEWFILE);
  4616.         }
  4617.         else
  4618.             Stream = Open(WindowName,MODE_NEWFILE);
  4619.     }
  4620.     else
  4621.         Stream = NULL;
  4622.  
  4623.     if(GoodStream(Stream))
  4624.     {
  4625.         ThisProcess -> pr_ConsoleTask = ((struct FileHandle *)BADDR(Stream)) -> fh_Type;
  4626.  
  4627.         OutputStream = Open("*",MODE_NEWFILE);
  4628.     }
  4629.     else
  4630.         OutputStream = NULL;
  4631.  
  4632.     if(Stream && OutputStream)
  4633.     {
  4634.         Result = SystemTags(Command,
  4635.             SYS_Input,    Stream,
  4636.             SYS_Output,    OutputStream,
  4637.             SYS_UserShell,    TRUE,
  4638.         TAG_DONE);
  4639.     }
  4640.     else
  4641.     {
  4642.         Result = SystemTags(Command,
  4643.             SYS_UserShell,    TRUE,
  4644.         TAG_DONE);
  4645.     }
  4646.  
  4647.     if(OutputStream)
  4648.         Close(OutputStream);
  4649.  
  4650.     if(Stream)
  4651.         Close(Stream);
  4652.  
  4653.     ThisProcess -> pr_ConsoleTask = OldConsoleTask;
  4654.  
  4655.     if(OtherName)
  4656.         FreeVecPooled(OtherName);
  4657.  
  4658.     return(Result);
  4659. }
  4660.  
  4661.     /* AskDial(struct Window *Parent):
  4662.      *
  4663.      *    This is called when the user is about to start dialing. If the
  4664.      *    dial button/menu item is available with the protective mode
  4665.      *    enabled, a message will be displayed, asking if the line
  4666.      *    should be hung up before proceeding.
  4667.      */
  4668.  
  4669. BOOL __regargs
  4670. AskDial(struct Window *Parent)
  4671. {
  4672.     if(!DialItemsAvailable)
  4673.     {
  4674.         if(MyEasyRequest(Parent,LocaleString(MSG_CANNOT_DIAL_BECAUSE_TXT),LocaleString(MSG_DIAL_CANCEL_TXT)))
  4675.             FullHangup(TRUE);
  4676.         else
  4677.             return(FALSE);
  4678.     }
  4679.  
  4680.     return(TRUE);
  4681. }
  4682.